package com.game.battle.common.map;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.game.battle.common.BattleEnum;
import com.game.battle.common.BattleEnum.EnumAttackRangeType;
import com.game.battle.common.BattleEnum.EnumSceneUnitType;
import com.game.battle.common.BattleEnum.EnumSkillType;
import com.game.battle.common.BattleStep;
import com.game.battle.common.ConditionUnit;
import com.game.battle.common.FightSceneUnit;
import com.game.battle.common.GridPosition;
import com.game.battle.common.MonsterFightUnit;
import com.game.battle.common.ObstacleFightUnit;
import com.game.battle.common.PlayerFightUnit;
import com.game.battle.common.Shield;
import com.game.battle.common.ai.AiConst;
import com.game.battle.common.ai.MonsterAI;
import com.game.battle.common.item.DropItem;
import com.game.battle.common.math.Box2;
import com.game.battle.common.math.Circle2;
import com.game.battle.common.math.ColidTest;
import com.game.battle.common.math.Segment2;
import com.game.battle.common.math.Vector2;
import com.game.battle.common.weapon.Weapon;
import com.game.battle.config.AiActionConfig;
import com.game.battle.config.AiConfig;
import com.game.battle.config.AttributeNumberConfig;
import com.game.battle.config.CounterConfig;
import com.game.battle.config.DropItemConfig;
import com.game.battle.config.DungeonConditionConfig;
import com.game.battle.config.DungeonConfig;
import com.game.battle.config.SkillConfig;
import com.game.battle.config.TalentEffectConfig;
import com.game.battle.config.WeaponConfig;
import com.game.battle.config.XMLTemplateService;
import com.game.battle.config.map.BattleMapConfig.BattleMapItemConfig;
import com.game.battle.config.map.MapLevelConfig.MapLevelItemConfig;
import com.game.battle.service.battle.AchievementService;
import com.game.battle.service.battle.AchievementService.AchievementType;
import com.game.battle.util.ProbabilityGift;
import com.game.core.util.RandomExt;
import com.game.dbpersistence.game.entity.ItemEntity;
import com.game.message.proto.battle.BattleProtoBuf.AttackAddEffect;
import com.game.message.proto.battle.BattleProtoBuf.BWStartBattleRES;
import com.game.message.proto.battle.BattleProtoBuf.BattleStepType;
import com.game.message.proto.battle.BattleProtoBuf.MGameOver;
import com.game.message.proto.battle.BattleProtoBuf.MStageInfo;
/**
 * 战斗地图
 * @author game
 *
 */
public class BattleMap {
	public String roomOwner;
	public static final int deployStage = 1;
	public static final int realStage = 2;
	public BattleMapItemConfig battleMapItemConfig;
	public MapLevelItemConfig mapLevelItemConfig;
	public DungeonConfig dungeonConfig;
	public int currentStage;
	public List<LevelPlayerConfig2ID> playerBornPosList;
	public int battleRound;
	public int battleStep;
	public DungeonConditionConfig dungeonConditionConfig;
	
	public ConcurrentHashMap<Integer, ItemEntity> monstersDropItems = new ConcurrentHashMap<>();
	public ConcurrentHashMap<Integer, ItemEntity> gamecopyDropItems = new ConcurrentHashMap<>();
	
	public HashMap <String, List<ItemEntity>> playerAchievementItems = new HashMap<>(); 
	
	public ConcurrentHashMap<Integer, ConditionUnit> dungeonConditionUnits1 = new ConcurrentHashMap<>();
	public ConcurrentHashMap<Integer, ConditionUnit> dungeonConditionUnits2 = new ConcurrentHashMap<>();
	public ConcurrentHashMap<Integer, ConditionUnit> dungeonConditionUnits3 = new ConcurrentHashMap<>();
	
	public static int KillAllMonster = 101;//击杀所有怪物
	public static int KillBossMonster = 102;//击杀BOSS（怪物ID）
	public static int GotoSpecifiedPoint = 103;//走到指定的坐标
	public static int EscortTargetSuccess = 104;//护送目标走到指定的坐标
	public static int PlayerLiveReachRounds = 105;//玩家存活过指定回合数
	public static int NpcLiveReachRounds = 106;//指定NPC存活过指定回合数
	public static int AllPlayersFailed = 201;//所有玩家死亡
	public static int PlayersOverRoundsCount = 202;//行动不超过指定回合数
	public static int EscortTargetFailed = 203;//护送目标死亡
	public static int GameInterruptExit = 204;//副本掉线
	
//	public static final class GridDatasList{
//		public GridDatasList(){
//			
//		}
//		public List<GridDatas> gridDatasList;
//	}
	public static final class GridDatas{
		public int step;
        public int width;
        public int height;
        public List<GridData> datas;
        public Position pos;
    }
	
	public static final class GridData{
		public GridData(){
			
		}
        public int X;
        public int Y;
        public boolean IsWall;
        public Position pos;
	}
	
   public static final class LevelStepInfos
    {
	    public LevelStepInfos(){
	    	
	    }
	    public int gridID;
        public List<LevelStepInfo> steps;
        public List<LevelPlayerConfig2ID> players;
    }

    // type = 1 怪物 type = 2 障碍物
    public static final class LevelStepInfo
    {
    	public LevelStepInfo(){
    		
    	}
        public int type;
        public List<LevelMyConfig2ID> info;
    }

    public static final class LevelMyConfig2ID
    {
    	public LevelMyConfig2ID(){
    		
    	}
        public int NodeX;
        public int NodeY;
        public int cfgID;
        public int isNotCanAtkObs;//0是能被打 1是不能被打
        public Rotation Rotation;
    }
    
    public static final class LevelPlayerConfig2ID
    {
    	public LevelPlayerConfig2ID(){
    		
    	}
        public int NodeX;
        public int NodeY;
        public Rotation Rotation;
    }
    
    public static final class Rotation
    {
    	public Rotation(){
    		
    	}
    	public float x;
    	public float y;
    	public float z;
    }
    
    //玩家操作栈
//    public Stack<BattleStep> stepStack = new Stack<>();
    public Map<String, Stack<BattleStep>> playerStacks = new HashMap<>();
	public GridDatas gridDatas;
	public Grid[][] grids;
	
	private ConcurrentHashMap<String, PlayerFightUnit> players = new ConcurrentHashMap<>();
	private ConcurrentHashMap<Integer, String> unitIdToAccountMap = new ConcurrentHashMap<>();
	private ConcurrentHashMap<String, PlayerFightUnit> deployPlayers = new ConcurrentHashMap<>();
	//玩家操作list 按顺序操作
	public List<String> playerOperList = new ArrayList<>();
	public int playerOperIndex = 0;
	
	private ConcurrentHashMap<Integer,List<FightSceneUnit>> sceneObjs = new ConcurrentHashMap<>();
	private ConcurrentHashMap<Integer,List<FightSceneUnit>> deploySceneObjs = new ConcurrentHashMap<>();
	
	public AchievementService achievementService;
	
	public BattleMap(MapLevelItemConfig mapLevelItemConfig,BattleMapItemConfig battleMapItemConfig, DungeonConfig dungeonConfig) {
		 this.currentStage = 1;
		 this.playerBornPosList = new ArrayList<>();
		 this.mapLevelItemConfig = mapLevelItemConfig;
		 this.battleMapItemConfig = battleMapItemConfig;
		 this.dungeonConfig = dungeonConfig;
		 this.battleRound = 1;
		 this.battleStep = 1;
		 initDungeonConditionUnits(dungeonConfig);
	}
	
	public void initAfterMemberJoined() {
		 this.achievementService = new AchievementService(this);
	}
	
	public void initDungeonConditionUnits(DungeonConfig dungeonConfig){
		 if(dungeonConfig!=null) {
			 String winConditions = dungeonConfig.getWin();
			 String failConditions = dungeonConfig.getFail();
			 String rawardItems =dungeonConfig.getReward();
			 if((winConditions!=null)&&(!winConditions.isEmpty())) {
				 String[] wins = winConditions.split("\\|");
				 int index = 0;
				 for(String winCon: wins) {
					 String[] win = winCon.split(",");
					 index ++;
					 for(String w: win) {
						 int id = Integer.parseInt(w);
						 DungeonConditionConfig dungeonCondition = XMLTemplateService.dungeonConditionConfigMap.get(id);
						 if(dungeonCondition!=null) {
							 ConditionUnit conditionUnit = new ConditionUnit();
							 conditionUnit.setId(id);
							 conditionUnit.setStatus(0);
							 conditionUnit.setType(dungeonCondition.getType());
							 conditionUnit.setCondition(dungeonCondition.getCondition());
							 conditionUnit.setWord(dungeonCondition.getWord());
							 if(index == 1) {
								 dungeonConditionUnits1.put(id, conditionUnit);
							 }else if(index == 2) {
								 dungeonConditionUnits2.put(id, conditionUnit);
							 }else if(index == 3) {
								 dungeonConditionUnits3.put(id, conditionUnit);
							 } 
						 }
					 }
				 }
			 }
			 if((failConditions!=null)&&(!failConditions.isEmpty())) {
				 String[] fails = failConditions.split("\\|");
				 int index = 0;
				 for(String failCon: fails) {
					 String[] fail = failCon.split(",");
					 index ++;
					 for(String f: fail) {
						 int id = Integer.parseInt(f);
						 DungeonConditionConfig dungeonCondition = XMLTemplateService.dungeonConditionConfigMap.get(id);
						 if(dungeonCondition!=null) {
							 ConditionUnit conditionUnit = new ConditionUnit();
							 conditionUnit.setId(id);
							 conditionUnit.setStatus(0);
							 conditionUnit.setType(dungeonCondition.getType());
							 conditionUnit.setCondition(dungeonCondition.getCondition());
							 conditionUnit.setWord(dungeonCondition.getWord());
							 if(index == 1) {
								 dungeonConditionUnits1.put(id, conditionUnit);
							 }else if(index == 2) {
								 dungeonConditionUnits2.put(id, conditionUnit);
							 }else if(index == 3) {
								 dungeonConditionUnits3.put(id, conditionUnit);
							 } 
						 }
					 }
				 }
			 }
			 if((rawardItems!=null)&&(!rawardItems.isEmpty())) {
				 String[] items = rawardItems.split("\\|");
				 for(String item: items) {
						int itemId = Integer.parseInt(item.split(",")[0]);
						int itemCnt = Integer.parseInt(item.split(",")[1]);
						ItemEntity itemEntity = new ItemEntity();
						itemEntity.setItemId(itemId);
						itemEntity.setCount(itemCnt);
						gamecopyDropItems.put(itemId, itemEntity);
				 }
			 }
		 }
    }
	
	public Vector2 getTargetGridPos(int row, int column){
        MyRenderGrid grid = getTargetGrid(row, column);
        return grid.oriPos;
    }
	//target 为目标的grid坐标
//	public GridPosition autoSearchGrid(boolean IsRaycastWall, int currentGridX, int currentGridY,
//            Vector2 targetVec, BattleEnum.EnumAttackRangeType attackRangeType, float Range,int stage){
////    	List<Grid> neighborGrids = new ArrayList<Grid>();
//    	FightSceneUnit target = getFightUnitByVec(targetVec,stage);
//		switch (attackRangeType)
//		{
//			case Arc:
//			case Rect:
//			case Circle:
//			case None:
//			case Bullet:
//				Vector2 enemyPos = getTargetGridPos(target.gridPos.getX(), target.gridPos.getY());
//				
//				float distance = Range;
//				
//				// 找到最靠近自己的一列
//				// 如果自己列>敌人列
//				if (currentGridY >= target.gridPos.getY()){
//					for (int i = currentGridY; i >= 0; i--){
//						GridPosition targetGrid = getNoRayCastObstacleGirdInTargetColumn(IsRaycastWall, currentGridX, currentGridY, i, target.gridPos,
//				                                                                        enemyPos, distance + target.getRadius());
//				
//						if (targetGrid != null){
//							return targetGrid;
//						}
//					}
//				
//					// 如果没有，只好反过来找一遍。。
//					for (int i = currentGridY + 1; i < gridWidthNum; i++){
//						GridPosition targetGrid = getNoRayCastObstacleGirdInTargetColumn(IsRaycastWall, currentGridX, currentGridY, i, target.gridPos,
//					                                                                        enemyPos, distance + target.getRadius());
//						if (targetGrid != null)
//						{
//							return targetGrid;
//						}
//					}
//				}
//				// 如果自己列<敌人列
//				else if (currentGridY < target.gridPos.getY()){
//					for (int i = currentGridY; i < gridWidthNum; i++){
//						GridPosition targetGrid = getNoRayCastObstacleGirdInTargetColumn(IsRaycastWall, currentGridX, currentGridY, i, target.gridPos,
//				                                                                        enemyPos, distance + target.getRadius());
//						if (targetGrid != null){
//							return targetGrid;
//						}
//					}
//				
//					// 如果没有，只好反过来找一遍。。
//					for (int i = currentGridY - 1; i >= 0; i--){
//						GridPosition targetGrid = getNoRayCastObstacleGirdInTargetColumn(IsRaycastWall, currentGridX, currentGridY, i, target.gridPos,
//					                                                                        enemyPos, distance + target.getRadius());
//					
//						if (targetGrid != null){
//							return targetGrid;
//						}
//					}
//				}
//				
//				break;
////			case Bullet:
////				neighborGrids = getEightNeighborGrids(target.gridPos.getX(), target.gridPos.getY());
////				return getNearestGrid2(currentGridX, currentGridY, neighborGrids);
////				//break;
//				default:
//					break;
//					
////			case None:
////				return new GridPosition(currentGridX, currentGridY);	
//			}
//	
//	
//		return null;
//    }
	
	
	/**
	 * 寻找fightunit
	 * @param targetVec
	 * @return
	 */
	private FightSceneUnit getFightUnitByVecForSerach(Vector2 targetVec, int stage) {
		List<MonsterFightUnit> enemys = getAliveMonsters(stage);
		if(enemys != null){
			for(FightSceneUnit enemy : enemys){
				if(enemy.gridPos.getX() == (int)targetVec.x && enemy.gridPos.getY() == (int)targetVec.y){
					return enemy;
				}
			}
		}
		
		
		List<FightSceneUnit> obstacles = getAliveObstacles(stage);
		if(obstacles != null){
			for(FightSceneUnit obstacle : obstacles){
				if(obstacle.gridPos.getX() == (int)targetVec.x && obstacle.gridPos.getY() == (int)targetVec.y){
					return obstacle;
				}
			}
		}
		
		
		for(PlayerFightUnit player : getAlivePlayers(stage)){
			if(player.gridPos.getX() == (int)targetVec.x && player.gridPos.getY() == (int)targetVec.y){
				return player;
			}
		}
		return null;
	}
	
	private FightSceneUnit getFightUnitByVec(Vector2 targetVec,int stage) {
		List<MonsterFightUnit> enemys = getMonsters(stage);
		if(enemys != null){
			for(FightSceneUnit enemy : enemys){
				if(enemy.gridPos.getX() == (int)targetVec.x && enemy.gridPos.getY() == (int)targetVec.y){
					return enemy;
				}
			}
		}
		
		
		List<FightSceneUnit> obstacles = getObstacles(stage);
		if(obstacles != null){
			for(FightSceneUnit obstacle : obstacles){
				if(obstacle.gridPos.getX() == (int)targetVec.x && obstacle.gridPos.getY() == (int)targetVec.y){
					return obstacle;
				}
			}
		}
		
		for(Entry<String, PlayerFightUnit> playerEntry : getPlayers(stage).entrySet()){
			if(playerEntry.getValue().gridPos.getX() == (int)targetVec.x && playerEntry.getValue().gridPos.getY() == (int)targetVec.y){
				return playerEntry.getValue();
			}
		}
		return null;
	}
	
//	private FightSceneUnit getPlayerUnitByVec(Vector2 targetVec,int stage) {
//		for(Entry<String, PlayerFightUnit> playerEntry : getPlayers(stage).entrySet()){
//			if(playerEntry.getValue().gridPos.getX() == (int)targetVec.x && playerEntry.getValue().gridPos.getY() == (int)targetVec.y){
//				return playerEntry.getValue();
//			}
//		}
//		return null;
//	}
	
//	private FightSceneUnit getObstacleUnitByVec(Vector2 targetVec,int stage) {
//		List<FightSceneUnit> obstacles = getObstacles(stage);
//		if(obstacles != null){
//			for(FightSceneUnit obstacle : obstacles){
//				if(obstacle.gridPos.getX() == (int)targetVec.x && obstacle.gridPos.getY() == (int)targetVec.y){
//					return obstacle;
//				}
//			}
//		}
//		return null;
//	}
	
	

//	private GridPosition getNoRayCastObstacleGirdInTargetColumn(boolean IsRaycastWall, int currentGridX, int currentGridY, int targetCol,
//             GridPosition targetPos, Vector2 enemyPos, float distance){
//		 List<Grid> neighborGrids = new ArrayList<Grid>();
//		 
//		 for (int i = 0; i < gridHeightNum; i++){
//	            Grid node = grids[i][targetCol];
//
//	            if ((node.x == currentGridX && node.y == currentGridY) || !node.isWall)
//	            {
//	                Vector2 pos = getTargetGridPos(i, targetCol);
//	                Vector2 dir = Vector2.sub(enemyPos, pos);
//	                
//	       		 	Segment2 segment = new Segment2(pos, getTargetGridPos(targetPos.getX(),targetPos.getY()));
//	                // 在范围内
//	                if (dir.getMagnitude() <= distance)
//	                {
//	                    if(IsRaycastWall)
//	                    {
//	                    	 boolean needAdd = true;
//	                    	List<FightSceneUnit> obstacles = getObstacles(realStage);
//	                    	if(obstacles != null){
//	                    		for(FightSceneUnit obstacle : getObstacles(realStage)){
//		                    		//Segment2 segment = new Segment2(getTargetGridPos(currentGridX, currentGridY), getTargetGridPos(obstacle.gridPos.getX(),obstacle.gridPos.getY()));
//		                    		if(obstacle.getCurrentHp() <= 0){
//		                    			continue;
//		                    		}
//		                    		boolean isClide = ColidTest.testSegment2Box2(segment, getTargetGrid(obstacle.gridPos.getX(),obstacle.gridPos.getY()).gridBox2);
//		                    		if(isClide){
//		                    			needAdd = false;
//		                    			break;
//		                    		}
//		                    	}
//	                    	}
//
//	                        if (needAdd)
//	                        {
//	                            neighborGrids.add(node);
//	                        }
//	                    }
//	                    else
//	                    {
//	                        neighborGrids.add(node);
//	                    }
//	                }
//	            }
//	        }
//		 if (neighborGrids.size() > 0){
//            return getNearestGrid2(currentGridX, currentGridY, neighborGrids);
//		 }
//		 return null;
//	 }
	
	  // 检测周围8个格子
    public List<Grid> getEightNeighborGrids(int x, int y)
    {
        List<Grid> neighborGrids = new ArrayList<Grid>();

        // 检测周围8个格子
        if ((x > 0) && (y > 0))
        {
            neighborGrids.add(grids[x - 1][y - 1]);
        }

        if (y > 0)
        {
            neighborGrids.add(grids[x][y - 1]);
        }

        if ((x < gridHeightNum - 1) && (y > 0))
        {
            neighborGrids.add(grids[x + 1][y - 1]);
        }

        if (x > 0)
        {
            neighborGrids.add(grids[x - 1][y]);
        }

        if (x < gridHeightNum - 1)
        {
            neighborGrids.add(grids[x + 1][y]);
        }

        if ((x > 0) && (y < gridWidthNum - 1))
        {
            neighborGrids.add(grids[x - 1][y + 1]);
        }

        if (y < gridWidthNum - 1)
        {
            neighborGrids.add(grids[x][y + 1]);
        }

        if ((x < gridHeightNum - 1) && (y < gridWidthNum - 1))
        {
            neighborGrids.add(grids[x + 1][y + 1]);
        }

        return neighborGrids;
    }
    
    private GridPosition getNearestGrid2(int currentGridX, int currentGridY, List<Grid> neighborGrids)
    {
    	Grid targetGrid = null;

        int minCount = Integer.MAX_VALUE;

        if (neighborGrids.size() > 0)
        {
            if (neighborGrids.size()== 1)
            {
                targetGrid = neighborGrids.get(0);
            }
            else
            {
                for (int i = 0; i < neighborGrids.size(); i++)
                {
                    if (neighborGrids.get(i).x == currentGridX && neighborGrids.get(i).y == currentGridY)
                    {
                        return new GridPosition(currentGridX, currentGridY);
                    }
                    else if (!neighborGrids.get(i).isWall)
                    {
                        List<PathNode> path = search(currentGridX, currentGridY, neighborGrids.get(i).x, neighborGrids.get(i).y);

                        if (path != null && path.size() < minCount)
                        {
                            targetGrid =  neighborGrids.get(i);
                            minCount = path.size();
                        }
                    }
                }
            }

            if (targetGrid != null)
            {
                return new GridPosition(targetGrid.x, targetGrid.y);
            }
        }

        return null;
    }
    
    /**
     * 取得一个点周围的gridLength 距离内的点
     * @param x
     * @param y
     * @param gridLength
     * @return
     */
    public List<GridPosition> getNeighborGrids(int x, int y, int gridLength)
    {
        int minX = x - gridLength;
        int maxX = x + gridLength;

        int minY = y - gridLength;
        int maxY = y + gridLength;

        if (minX < 0) minX = 0;
        if (minY < 0) minY = 0;

        if (maxX >= gridHeightNum) maxX = gridHeightNum - 1;
        if (maxY >= gridWidthNum) maxY = gridWidthNum - 1;

        List<GridPosition> rangeGrids = new ArrayList<GridPosition>();

        for (int i = minX; i <= maxX; i++)
        {
            for (int j = minY; j <= maxY; j++)
            {
                rangeGrids.add(new GridPosition(i, j));
            }
        }

        return rangeGrids;
    }
    
    /**
     * 取得一个点周围的空点
     * @param x
     * @param y
     * @param gridLength
     * @return
     */
    public List<GridPosition> getNeighborEmptyGrids(int x, int y, int gridLength,int stage){
    	List<GridPosition> resultGridPositions = new ArrayList<>();
    	List<GridPosition> neighborGrids = getNeighborGrids(x, y, gridLength);
    	for(GridPosition gridPosition : neighborGrids){
    		FightSceneUnit unit = getFightUnitByVecForSerach(new Vector2(gridPosition.getX(), gridPosition.getY()),stage);
    		if(unit == null){
    			resultGridPositions.add(gridPosition);
    		}
    	}
    	
    	return resultGridPositions;
    }
    
	public void updateGridDatasByLevelCfg(int stage){
		//先清空上一阶段的
		sceneObjs.clear();
		deploySceneObjs.clear();
		
		ObjectMapper mapper = new ObjectMapper();
		try {
			
			LevelStepInfos levelStepInfos = null;
			if(stage == 1){
				levelStepInfos = (LevelStepInfos)mapper.readValue(mapLevelItemConfig.getStep1(), new TypeReference<LevelStepInfos>(){});
			}else if(stage == 2){
				levelStepInfos = (LevelStepInfos)mapper.readValue(mapLevelItemConfig.getStep2(), new TypeReference<LevelStepInfos>(){});
			}else {
				levelStepInfos = (LevelStepInfos)mapper.readValue(mapLevelItemConfig.getStep3(), new TypeReference<LevelStepInfos>(){});
			}
			
			List<FightSceneUnit> fightSceneUnits;
			List<LevelStepInfo> steps = levelStepInfos.steps;
			List<LevelPlayerConfig2ID> bornPositions = levelStepInfos.players;
			for(LevelStepInfo stepInfo : steps){
				for(LevelMyConfig2ID cfg : stepInfo.info){
					if(!sceneObjs.containsKey(stepInfo.type)){
						fightSceneUnits = new ArrayList<>();
					}else {
						fightSceneUnits = sceneObjs.get(stepInfo.type);
					}
					Rotation rotation = cfg.Rotation;
					if(stepInfo.type == EnumSceneUnitType.Monster.ordinal()){
						fightSceneUnits.add(new MonsterFightUnit(cfg.cfgID,cfg.NodeX,cfg.NodeY,rotation));
					}else if(stepInfo.type == EnumSceneUnitType.Obstacle.ordinal()){
						fightSceneUnits.add(new ObstacleFightUnit(cfg.cfgID,cfg.NodeX,cfg.NodeY,cfg.isNotCanAtkObs,rotation));
					}
					
					sceneObjs.put(stepInfo.type, fightSceneUnits);
				}
			}
			
			playerBornPosList = bornPositions; 
			
			updateDeployUnitsByRealSceneUnits();
			
			for (int x = 0; x < gridDatas.width; x++){
	            for (int y = 0; y < gridDatas.height; y++){
	            	Grid grid = grids[x][y];
					for(LevelStepInfo stepInfo : steps){
						for(LevelMyConfig2ID cfg : stepInfo.info){
							if(cfg.NodeX == x && cfg.NodeY == y){
								grid.isWall = true;
							}
						}
					}
					for(LevelPlayerConfig2ID playerPos2 : playerBornPosList){
						if(x == playerPos2.NodeX && y == playerPos2.NodeY){
							grid.isWall = true;
						}
					}
	            }
			}
		} catch (JsonParseException e) {
			e.printStackTrace();
		} catch (JsonMappingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 刷新buff相关信息
	 */
	public void refreshBuff() {
		ConcurrentHashMap<String, PlayerFightUnit> players = getPlayers(realStage);
		List<MonsterFightUnit> monsterFightUnits = getMonsters(realStage);
		
		for(PlayerFightUnit playerUnit : players.values()){
			playerUnit.roundRefreshBuff();
		}
		
		for(FightSceneUnit monsterUnit : monsterFightUnits){
			monsterUnit.roundRefreshBuff();
		}
	}

	
	public void updateDeployUnitsByRealSceneUnits() {
		deploySceneObjs.clear();
	
		for(Entry<Integer, List<FightSceneUnit>> entry: sceneObjs.entrySet()){
			List<FightSceneUnit> fightSceneUnits;
			if(!deploySceneObjs.containsKey(entry.getKey())){
				fightSceneUnits = new ArrayList<>();
			}else {
				fightSceneUnits = deploySceneObjs.get(entry.getKey());
			}
			for(FightSceneUnit unit : entry.getValue()){
				if(unit.getCurrentHp() > 0){
					fightSceneUnits.add(unit.clone());
				}
			}
			deploySceneObjs.put(entry.getKey(), fightSceneUnits);
		}
		
		deployPlayers.clear();
		for(Entry<String,PlayerFightUnit> playerEntry : players.entrySet()){
			playerEntry.getValue().setInitWeaponId(playerEntry.getValue().getSelectWeaponId());
			deployPlayers.put(playerEntry.getKey(),(PlayerFightUnit)playerEntry.getValue().clone());
		}
	}
	

	/**
	 * 每个操作更新地图信息(这里的阶段指的是部署还是执行阶段)
	 */
	public void updateGridDatas(int stage) {
		for (int x = 0; x < gridDatas.width; x++){
            for (int y = 0; y < gridDatas.height; y++){
            	Grid grid = grids[x][y];
        		FightSceneUnit enemyUnit = getFightUnitByVecForSerach(new Vector2(x, y),stage);
				if(enemyUnit != null){
					grid.isWall = true;
					continue;
				}
				
				grid.isWall = false;
            }
		}
	}
	
	
	public List<PathNode> search(int startX, int startY, int endX, int endY) {
		AStar aStar = new AStar(gridDatas.width,gridDatas.height,grids);
		LinkedList<PathNode> pathList = aStar.search(true, startX, startY, endX, endY, 0);
		return pathList;
	}
	
	public List<PathNode> search(boolean ignoreObstacle, int startX, int startY, int endX, int endY, float range, float radius) {
		float distance = range + radius;
		AStar aStar = new AStar(gridDatas.width,gridDatas.height,grids);
		LinkedList<PathNode> pathList = aStar.search(ignoreObstacle, startX, startY, endX, endY, distance);
		//boolean hasWallInPath = false;
		//以下代码是清除在攻击范围内的路径点，这些点是无效的，剩下最后一个路径点就是最佳攻击点。
		if(( distance > 0.0f )&&(pathList!=null && pathList.size()>0)) {
			PathNode lastPathNode = null;
			for(int i = pathList.size()-1; i>=0; i--) {
				PathNode pathNode = pathList.get(i);
				if(pathNode==null) {
					continue;
				}
				if(pathNode.gethCost() <= distance) {
					if(lastPathNode==null){
						if(pathNode.getIsWall()) {
							pathList.remove(pathNode);
							//hasWallInPath = true;
						}else {
							lastPathNode = pathNode;
						}
					}else if((lastPathNode!=null)&&(lastPathNode.gethCost() < pathNode.gethCost())) {
						if(pathNode.getIsWall()) {
							pathList.remove(pathNode);
							//hasWallInPath = true;
						}else {
							pathList.remove(lastPathNode);
							lastPathNode = pathNode;
						}
					}else if((lastPathNode!=null)&&(lastPathNode.gethCost() >= pathNode.gethCost())) {
						pathList.remove(pathNode);
					}
				}
			}
		}
//		if((ignoreObstacle == false)&&(hasWallInPath == true)&&(pathList!=null)&&(pathList.size()>0)) {		
//			pathList = aStar.search(true, startX, startY, pathList.get(pathList.size()-1).getX(), pathList.get(pathList.size()-1).getY(), 0);
//		}
		return pathList;
	}
	
	
	
	
	// 横行格子数
    public int gridWidthNum = 24;
    // 纵行格子数
    public int gridHeightNum = 11;
    
    public List<MyRenderGrid> gridObjects = new ArrayList<MyRenderGrid>();
    
    
	
	public List<FightSceneUnit> getGridsInAttackRange(boolean isPlayer, Vector2 casterPos,Vector2 targetPos, FightSceneUnit target,
			EnumAttackRangeType attackRangeType, float width, float range,int stage){
		List<FightSceneUnit> reachFightSceneUnits = new ArrayList<>();
		 if (attackRangeType == EnumAttackRangeType.Bullet)
	     {
	         //SetColorInAttackRangeGrids(null);
	     }
	     else
	     {
	         List<FightSceneUnit> obstacleResults = getObstacleInRange(attackRangeType, width, range, casterPos,targetPos,stage);
	         // 处理目标选中
	         List<FightSceneUnit> monsterResults = getAttackTargetInRange(isPlayer, casterPos,targetPos, attackRangeType, width, range,stage);
	         if(obstacleResults != null){
	        	 for (FightSceneUnit unit : obstacleResults) {
					if(unit.getCurrentHp() > 0 && ((ObstacleFightUnit)unit).getIsNotCanAtkObs() == 0){
						reachFightSceneUnits.add(unit);
					}
				}
	         }
	         if(monsterResults != null){
	        	 for(FightSceneUnit unit : monsterResults) {
					if(unit.getCurrentHp() > 0){
						reachFightSceneUnits.add(unit);
					}
				}
	         }
	     }
		 return reachFightSceneUnits;
	}
	//选到的目标包括死了的 为了策划的鞭尸要求。。
	public List<FightSceneUnit> useSkill(SkillConfig skillConfig,boolean isPlayer, Vector2 casterPos,Vector2 targetPos, FightSceneUnit target,
			EnumAttackRangeType attackRangeType,int stage) {
		   float width = 1f;
	       float range = 1f;

	       switch(attackRangeType)
	       {
	            case Arc:
	                width = skillConfig.getAngle();
	                range = skillConfig.getRadius();
	                break;
	            case Rect:
	                width = skillConfig.getRadius();
	                range = skillConfig.getMaxDist();
	                break;
	            case Circle:
	                width = skillConfig.getRadius();
	                range = skillConfig.getMaxRange();
	                break;
	            case None:
	            	 width = skillConfig.getRadius();
	                 range = skillConfig.getMaxRange();
	                 break;
	            case Bullet:
	            	 width = skillConfig.getRadius();
	                 range = skillConfig.getMaxDist();
	            default:
	                break;
	       }
	        
	    List<FightSceneUnit> reachFightSceneUnits = new ArrayList<>();
//		 if (attackRangeType == EnumAttackRangeType.Bullet)
//	     {
//	         //SetColorInAttackRangeGrids(null);
//	     }else 
	    if(attackRangeType == EnumAttackRangeType.None){
//	    	 reachFightSceneUnits.addAll(getTargetUnitsInDist(casterPos,range));
	    	Vector2 t2cDir = Vector2.sub(targetPos, casterPos);
	    	 if(target != null && t2cDir.getMagnitude()-target.getRadius() <= range){
	    		 reachFightSceneUnits.add(target);
	    	 }
	     }
	     else
	     {
	         List<FightSceneUnit> obstacleResults = getObstacleInRange(attackRangeType, width, range, casterPos,targetPos,stage);
	         // 处理目标选中
	         List<FightSceneUnit> enemyResults = getAttackTargetInRange(isPlayer, casterPos,targetPos, attackRangeType, width, range,stage);
	         if(obstacleResults != null){
	        	 for (FightSceneUnit unit : obstacleResults) {
//					if(unit.getCurrentHp() > 0){
	        		if(((ObstacleFightUnit)unit).getIsNotCanAtkObs() == 0){
	        			reachFightSceneUnits.add(unit);
	        		}
//					}
				}
	         }
	         if(enemyResults != null){
	        	 for(FightSceneUnit unit : enemyResults) {
//					if(unit.getCurrentHp() > 0){
					reachFightSceneUnits.add(unit);
//					}
				}
	         }
	     }
		 return reachFightSceneUnits;

	}
	
	
	// 圆心判断在范围内的怪物
    public List<FightSceneUnit> getTargetUnitsInDist(Vector2 castorPos, float range)
    {
        List<FightSceneUnit> results = new ArrayList<FightSceneUnit>();
        
        List<MonsterFightUnit> monsters = getMonsters(realStage);
        
        if(monsters != null){
        	for(FightSceneUnit monster : monsters){
        		if(getVectorDistance(castorPos, getTargetGridPos(monster.gridPos.getX(), monster.gridPos.getY())) <= range){
        			results.add(monster);
        		}
        	}
        }
        return results;
    }

	
	 // 选中攻击范围内的目标
    private List<FightSceneUnit> getAttackTargetInRange(boolean isPlayer,Vector2 casterPos,Vector2 targetPos, EnumAttackRangeType type, float width, float range,int stage)
    {
//        EnumSceneUnitType casterType = isPlayer ? EnumSceneUnitType.Player : EnumSceneUnitType.Enemy;
        List<FightSceneUnit> results = new ArrayList<FightSceneUnit>();
        
        Segment2 segment1 = new Segment2();
        Segment2 segment2 = new Segment2();
        Box2 box = new Box2();

        if (type == EnumAttackRangeType.Arc)
        {
            //Vector3 arcLine1 = Quaternion.Euler(0, -Width / 2, 0) * Caster.forward;
            //Vector3 arcLine2 = Quaternion.Euler(0, Width / 2, 0) * Caster.forward;

            Vector2 arcLine1 = ColidTest.rotateVectorByXZ(Vector2.normalize(Vector2.sub(targetPos, casterPos)), -width / 2);
            Vector2 arcLine2 =  ColidTest.rotateVectorByXZ(Vector2.normalize(Vector2.sub(targetPos, casterPos)), width / 2);

            Vector2 arcLine1End = Vector2.add(casterPos, Vector2.multi(arcLine1, range));
            Vector2 arcLine2End = Vector2.add(casterPos, Vector2.multi(arcLine2, range));
            segment1 = new Segment2(new Vector2(casterPos.x, casterPos.y), new Vector2(arcLine1End.x, arcLine1End.y));
            segment2 = new Segment2(new Vector2(casterPos.x, casterPos.y), new Vector2(arcLine2End.x, arcLine2End.y));

        }
        else if(type == EnumAttackRangeType.Rect || type == EnumAttackRangeType.Bullet)
        {
        	Vector2 castorForward = Vector2.normalize(Vector2.sub(targetPos, casterPos));
        	Vector2	castorRight = castorForward.right();
            Vector2 boxCenter = Vector2.add(casterPos, Vector2.multi(castorForward, range / 2));
            box = new Box2(new Vector2(boxCenter.x, boxCenter.y), new Vector2(castorRight.x, castorRight.y),
                                                                       new Vector2(castorForward.x, castorForward.y),
                                                                        new Vector2(width / 2, range / 2));

        }
        
        List<FightSceneUnit> targetSceneUnits;
        if(isPlayer){
        	targetSceneUnits = new ArrayList<>();
        	for (FightSceneUnit monsters : getMonsters(stage)) {
				targetSceneUnits.add(monsters);
			}
        }else {
        	targetSceneUnits = new ArrayList<>();
        	for (FightSceneUnit player : getPlayers(stage).values()) {
				targetSceneUnits.add(player);
			}
		}
//        for (FightSceneUnit target : sceneObjs.get(EnumSceneUnitType.Enemy.ordinal())){
        for (FightSceneUnit target : targetSceneUnits){
            // 取出怪物的圆形碰撞(真正坐标)
            Vector2 targetCenter = getTargetGridPos(target.gridPos.getX(), target.gridPos.getY());
            float radius = target.getRadius();
            Vector2 t2cDir = Vector2.sub(targetCenter, casterPos);

            boolean isInRange = false;

            // 扇形检测
            if (type == EnumAttackRangeType.Arc)
            {
                // 确保检测的物体距离小于最大距离
                if (t2cDir.getMagnitude() <= (radius + range))
                {
                    Circle2 circle = new Circle2(new Vector2(targetCenter.x, targetCenter.y), radius);

                    // 两边任意一边圆相交
                    if (ColidTest.testSegment2Circle2(segment1, circle) || 
                    		ColidTest.testSegment2Circle2(segment2, circle))
                    {
                        isInRange = true;
                    }

                    if (!isInRange)
                    {
                        // 目标与发射点的连线和扇形中线的夹角要小于等于扇形角度的一半
                        if (Vector2.angle(Vector2.normalize(t2cDir), Vector2.normalize(Vector2.sub(targetPos, casterPos))) <= (width / 2))
                        {
                            isInRange = true;
                        }
                    }
                }
            }
            // 矩形检测
            else if (type == EnumAttackRangeType.Rect || type == EnumAttackRangeType.Bullet)
            {
                Circle2 circle = new Circle2(new Vector2(targetCenter.x, targetCenter.y), radius);
                boolean test = ColidTest.testBox2Circle2(box, circle);

                if(test)
                {
                    isInRange = true;
                }              
            }
            // 圆的话直接判断发射者与被攻击者的圆心即可
            else if(type == EnumAttackRangeType.Circle)
            {
            	Vector2 t2cDir1 = Vector2.sub(targetCenter, targetPos);
                if (t2cDir1.getMagnitude() <= width)
                {
                    isInRange = true;
                }                    
            }

            //if (IsCheckCircleInRange(type, CasterPos, Caster, target, useSkill))
            if (isInRange)
            {
                results.add(target);
                continue;
            }
        }
        return results;
    }
    
    public ConcurrentHashMap<String, PlayerFightUnit> getPlayers(int stage){
		if(stage == deployStage){
			return deployPlayers;
		}else {
			return players;
		}
	}
    
    /**
     * 取得还活着的玩家
     * @param stage
     * @return
     */
    public List<PlayerFightUnit> getAlivePlayers(int stage){
    	List<PlayerFightUnit> playerList = new ArrayList<>();
    	if(stage == deployStage){
    		for(PlayerFightUnit deployPlayer : deployPlayers.values()){
    			if(deployPlayer.getCurrentHp() > 0){
    				playerList.add(deployPlayer);
    			}
    		}
		}else {
			for(PlayerFightUnit player : players.values()){
    			if(player.getCurrentHp() > 0){
    				playerList.add(player);
    			}
    		}
		}
    	
    	return playerList;
    }

	public List<MonsterFightUnit> getMonsters(int stage) {
		List<MonsterFightUnit> mosters = new ArrayList<>();
		if(stage == BattleMap.deployStage){
			List<FightSceneUnit> monsters = deploySceneObjs.get(EnumSceneUnitType.Monster.ordinal());
			if(monsters != null){
				for(FightSceneUnit monster : monsters){
					mosters.add((MonsterFightUnit)monster);
				}
			}
			
		}else if(stage == BattleMap.realStage){
			List<FightSceneUnit> monsters = sceneObjs.get(EnumSceneUnitType.Monster.ordinal());
			if(monsters != null){
				for(FightSceneUnit monster : monsters){
					mosters.add((MonsterFightUnit)monster);
				}
			}
		}
		return mosters;
	}
	
	public List<MonsterFightUnit> getAliveMonsters(int stage) {
		List<MonsterFightUnit> mosters = new ArrayList<>();
		if(stage == BattleMap.deployStage){
			List<FightSceneUnit> monsters = deploySceneObjs.get(EnumSceneUnitType.Monster.ordinal());
			if(monsters != null){
				for(FightSceneUnit monster : monsters){
					if(monster.getCurrentHp() > 0){
						mosters.add((MonsterFightUnit)monster);
					}
				}
			}
			
		}else if(stage == BattleMap.realStage){
			List<FightSceneUnit> monsters = sceneObjs.get(EnumSceneUnitType.Monster.ordinal());
			if(monsters != null){
				for(FightSceneUnit monster : monsters){
					if(monster.getCurrentHp() > 0){
						mosters.add((MonsterFightUnit)monster);
					}
				}
			}
		}
		return mosters;
	}
	
	public List<FightSceneUnit> getObstacles(int stage) {
		List<FightSceneUnit> obstacles = new ArrayList<>();
		if(stage == BattleMap.deployStage){
			obstacles = deploySceneObjs.get(EnumSceneUnitType.Obstacle.ordinal());
		}else if(stage == BattleMap.realStage){
			obstacles = sceneObjs.get(EnumSceneUnitType.Obstacle.ordinal());
		}
		return obstacles;
	}
	
	/**
	 * 取得还活着的障碍物
	 * @param stage
	 * @return
	 */
	public List<FightSceneUnit> getAliveObstacles(int stage) {
		List<FightSceneUnit> obstacles = new ArrayList<>();
		if(stage == BattleMap.deployStage){
			List<FightSceneUnit> obs = deploySceneObjs.get(EnumSceneUnitType.Obstacle.ordinal());
			if(obs != null){
				for(FightSceneUnit obstacle : obs){
					if(obstacle.getCurrentHp() > 0){
						obstacles.add(obstacle);
					}
				}
			}
			
		}else if(stage == BattleMap.realStage){
			List<FightSceneUnit> obs = sceneObjs.get(EnumSceneUnitType.Obstacle.ordinal());
			if(obs != null){
				for(FightSceneUnit obstacle : obs){
					if(obstacle.getCurrentHp() > 0){
						obstacles.add(obstacle);
					}
				}
			}
		}
		return obstacles;
	}

	private List<FightSceneUnit> getObstacleInRange(EnumAttackRangeType type, float width, float range,
			Vector2 casterPos,Vector2 targetPos,int stage) {
		  // 施法者碰撞范围
        Box2 box = new Box2();
        Circle2 casterCircle = new Circle2();

        Vector2 casterForward = Vector2.normalize(Vector2.sub(targetPos, casterPos));
        
        if (type == EnumAttackRangeType.Rect || type == EnumAttackRangeType.Bullet)
        {
        	
            Vector2 boxCenter = Vector2.add(casterPos, Vector2.multi(casterForward, range / 2));
            box = new Box2(new Vector2(boxCenter.x, boxCenter.y), casterForward.right(),
            														casterForward,
                                                                    new Vector2(width / 2, range / 2));
        }
        else if(type == EnumAttackRangeType.Circle)
        {
            casterCircle = new Circle2(targetPos, width);
        }

        List<FightSceneUnit> results = new ArrayList<FightSceneUnit>();

        // 遍历障碍物碰撞
        if (sceneObjs.containsKey(EnumSceneUnitType.Obstacle.ordinal()))
        {
            List<FightSceneUnit> units = getAliveObstacles(stage);

            for (int i = 0; i < units.size(); i++)
            {
                MyRenderGrid grid = getTargetGrid(units.get(i).gridPos.getX(), units.get(i).gridPos.getY());

                boolean isInRange = false;

                if (type == EnumAttackRangeType.Arc)
                {
                    isInRange = ColidTest.isCheckRectInArcRange(grid, width, range, casterPos, targetPos);
                }
                else if (type == EnumAttackRangeType.Rect || type == EnumAttackRangeType.Bullet)
                {
                    isInRange = ColidTest.testBox2Box2(box, grid.gridBox2);
                }
                else if(type == EnumAttackRangeType.Circle)
                {
                    isInRange =  ColidTest.testBox2Circle2(grid.gridBox2, casterCircle);
                }

                if (isInRange)
                {
                    results.add(units.get(i));
                }
            }
        }

        return results;
	}
	
	
	
	public MyRenderGrid getTargetGrid(int row, int column){
	  	int gridID = getIDByGridIndex(row, column);

        if (gridObjects.size() > gridID)
        {
            return gridObjects.get(gridID);
        }

        return null;
	}
	  
	private int getIDByGridIndex(int row, int column){
        return row * gridWidthNum + column;
	}

	public void initGridObjects(GridDatas gridDatas) {
		List<GridData> datas = gridDatas.datas;
		gridObjects.clear();
		for(GridData data : datas){
			MyRenderGrid gridInfo = new MyRenderGrid(getIDByGridIndex(data.X, data.Y), data.X, data.Y, new Vector2(data.pos.getX(), data.pos.getZ()), 1f);
            gridObjects.add(gridInfo);
		}
	}

	/**
	 * 
	 * @param playerUnit
	 */
	public void addPlayer(String account,PlayerFightUnit playerUnit) {
		this.playerOperList.add(account);
		this.players.put(account, playerUnit);
		this.unitIdToAccountMap.put(playerUnit.getId(), account);
		this.deployPlayers.put(account, (PlayerFightUnit)playerUnit.clone());
	}

	public FightSceneUnit getEnemyById(int targetId,int stage) {
		List<MonsterFightUnit> sceneUnits = getMonsters(stage);
		for(FightSceneUnit enemy : sceneUnits){
			if(enemy.getId() == targetId){
				return enemy;
			}
		}
		
		return null;
	}
	
	public FightSceneUnit getEnemyObstacleById(int targetId,int stage) {
		List<MonsterFightUnit> enemyUnits = getMonsters(stage);
		if(enemyUnits != null){
			for(FightSceneUnit enemy : enemyUnits){
				if(enemy.getId() == targetId){
					return enemy;
				}
			}
		}
		
		List<FightSceneUnit> obstacles = getObstacles(stage);
		if(obstacles != null){
			for(FightSceneUnit obstacle : obstacles){
				if(obstacle.getId() == targetId){
					return obstacle;
				}
			}
		}
		return null;
	}

	public void addStep(String account, BattleStep step) {
		Stack<BattleStep> stack = playerStacks.get(account);
		if(stack == null){
			stack = new Stack<>();
			playerStacks.put(account, stack);
		}
		stack.push(step);
		step.stepNumber = stack.size();
		
	}
	
	/**
	 * 根据技能类型计算出影响的物体 并提前记录下技能的伤害
	 * 
	 * （新增需求）这个时候要考虑触发的天赋效果，其他地方也要考虑 ，后期优化结构再整理
	 * @param step 
	 * @param playerUnit
	 * @param skillConfig
	 * @param reachUnits
	 * @param triggeredTalents 
	 * @return
	 */
	public List<FightSceneUnit> getEffectUnitsByDeploySkill(BattleStep step, FightSceneUnit fightUnit, SkillConfig skillConfig,
			List<FightSceneUnit> reachUnits,Map<Integer, FightSceneUnit> originUnitsMap, List<Integer> triggeredTalents) {
		for(FightSceneUnit unit : reachUnits){
			originUnitsMap.put(unit.getId(), unit.clone());
		}
		
		List<FightSceneUnit> realUnits = new ArrayList<>();
		if(skillConfig.getThroughObType() == 1){
			realUnits = suckSkillDeployEffect(step,fightUnit,reachUnits,skillConfig,triggeredTalents);
		}else if(skillConfig.getThroughObType() == 2){
			realUnits = destorySkillDeployEffect(step,fightUnit,reachUnits,skillConfig,triggeredTalents);
		}else if(skillConfig.getThroughObType() == 3){
			realUnits = ignoreSkillDeployEffect(step,fightUnit,reachUnits,skillConfig,triggeredTalents);
		}else if(skillConfig.getThroughObType() == 4){
			realUnits = allAttackSkillDeployEffect(step,fightUnit,reachUnits,skillConfig,triggeredTalents);
		}
		
		//这之前先把影响的单位记录下 后面放到battlestep中
		
//		//把行动者也记录上()
//		originUnitsMap.put(fightUnit.getId(), fightUnit.clone());
		checkTalentsAddBuff(fightUnit,realUnits,triggeredTalents);
		checkAddBuff(fightUnit,skillConfig,realUnits);
		if(!realUnits.contains(fightUnit)){
			realUnits.add(fightUnit);
		}
		return realUnits;
	}
	

	/**
	 * 检测是否触发了增加buff的天赋
	 * @param fightUnit
	 * @param realUnits
	 * @param triggeredTalents
	 */
	private void checkTalentsAddBuff(FightSceneUnit fightUnit,
			List<FightSceneUnit> realUnits, List<Integer> triggeredTalents) {
		List<HashMap<Integer,Integer>> effectList = getTalentEffect(triggeredTalents);
		List<Integer> buffIdList = getTriggeredTalentBuffList(effectList);
		for(int buffId : buffIdList){
			for(FightSceneUnit unit : realUnits){
				if(unit.unitType == EnumSceneUnitType.Monster.ordinal()){
					unit.addBuff(fightUnit, buffId);
				}
			}
		}
	}

	
	/**
	 * 取得触发的buff(这里策划会把值配为buffid)
	 * @param effectList
	 * @return
	 */
	private List<Integer> getTriggeredTalentBuffList(List<HashMap<Integer, Integer>> effectList) {
		List<Integer> triggeredBuffList = new ArrayList<>();
		for(HashMap<Integer, Integer> map : effectList){
			for(Entry<Integer,Integer> entry : map.entrySet()){
				if(entry.getKey() == 10000){
					triggeredBuffList.add(entry.getValue());
				}
			}
		}
		return triggeredBuffList;
	}


	/**
	 * 检测附加buff效果
	 * @param fightUnit
	 * @param skillConfig
	 * @param reachUnits
	 */
	public void checkAddBuff(FightSceneUnit attacker,
			SkillConfig skillConfig, List<FightSceneUnit> realUnits) {
		String addEffect = skillConfig.getAddEffect();
		if(addEffect == null || "".equals(addEffect)){
			return;
		}
		String[] effectParams = addEffect.split(",");
		int buffId = Integer.valueOf(effectParams[0]);
		if(buffId == 0){
			return;
		}
		int rate = Integer.valueOf(effectParams[1]);
//		int rate = 100;
		int target = Integer.valueOf(effectParams[2]);//0是自己 1是目标
		int rand = RandomExt.getInstance().getRandom(0, 101);
		if(rand < rate){
			if(target == 0){
				attacker.addBuff(attacker, buffId);
			}else{
				for(FightSceneUnit fightSceneUnit : realUnits){
					if(fightSceneUnit.unitType == EnumSceneUnitType.Monster.ordinal()
							|| fightSceneUnit.unitType == EnumSceneUnitType.Player.ordinal()){
						if(fightSceneUnit.getId() == attacker.getId()){
							continue;
						}
						fightSceneUnit.addBuff(attacker,buffId);
					}
				}
			}
		}
	}


	/**
	 * 忽略障碍物的技能
	 * @param step 
	 * @param fightUnit
	 * @param reachUnits
	 * @param skillConfig
	 * @param triggeredTalents 
	 * @return
	 */
	private List<FightSceneUnit> ignoreSkillDeployEffect(
			BattleStep step, FightSceneUnit attackerUnit, List<FightSceneUnit> reachUnits,
			SkillConfig skillConfig, List<Integer> triggeredTalents) {
		List<FightSceneUnit> realEffectUnits = getIgnoreSkillRealEffectUnits(attackerUnit,reachUnits,skillConfig);
		for(FightSceneUnit fightSceneUnit : realEffectUnits){
			int damage = calculateDamage(step,attackerUnit,skillConfig,fightSceneUnit,triggeredTalents,((PlayerFightUnit)attackerUnit).getSelectWeaponId(),deployStage);
			fightSceneUnit.deploySkillDamage = damage;
		}
		return realEffectUnits;
	}
	
	/**
	 * 获取忽略障碍物的技能真实打到的物体
	 * @param attackerUnit
	 * @param reachUnits
	 * @param skillConfig
	 * @return
	 */
	private List<FightSceneUnit> getIgnoreSkillRealEffectUnits(
			FightSceneUnit attackerUnit, List<FightSceneUnit> reachUnits,
			SkillConfig skillConfig) {
		
		List<FightSceneUnit> realEffectUnits = new ArrayList<>();
		for(FightSceneUnit fightSceneUnit : reachUnits){
			if(fightSceneUnit.unitType == EnumSceneUnitType.Monster.ordinal() 
					|| fightSceneUnit.unitType == EnumSceneUnitType.Player.ordinal()){
				realEffectUnits.add(fightSceneUnit);
			}
		}
		return realEffectUnits;
	}


	/**
	 * 直接摧毁障碍物的技能
	 * @param step 
	 * @param fightUnit
	 * @param reachUnits
	 * @param skillConfig
	 * @param triggeredTalents 
	 * @return
	 */
	private List<FightSceneUnit> destorySkillDeployEffect(
			BattleStep step, FightSceneUnit attackerUnit, List<FightSceneUnit> reachUnits,
			SkillConfig skillConfig, List<Integer> triggeredTalents) {
		for(FightSceneUnit fightSceneUnit : reachUnits){
			if(fightSceneUnit.unitType == EnumSceneUnitType.Monster.ordinal() 
					|| fightSceneUnit.unitType == EnumSceneUnitType.Player.ordinal()){
				int damage = calculateDamage(step,attackerUnit,skillConfig,fightSceneUnit,triggeredTalents,((PlayerFightUnit)attackerUnit).getSelectWeaponId(),deployStage);
				fightSceneUnit.deploySkillDamage = damage;
			}else if(fightSceneUnit.unitType == EnumSceneUnitType.Obstacle.ordinal()){
				int damage = fightSceneUnit.getCurrentHp();
				fightSceneUnit.deploySkillDamage = damage;
			}
		}
		return reachUnits;
	}

	/**
	 * 根据技能算伤害(技能能被障碍物吸收)
	 * @param step 
	 * @param fightUnit
	 * @param reachUnits
	 * @param skillConfig
	 * @param triggeredTalents 
	 */
	private List<FightSceneUnit> suckSkillDeployEffect(BattleStep step, FightSceneUnit attackerUnit,
			List<FightSceneUnit> reachUnits,SkillConfig skillConfig, List<Integer> triggeredTalents) {
		List<FightSceneUnit> realEffectUnits = getSuckSkillRealEffectUnits(attackerUnit,reachUnits,skillConfig); 
		deploySkill(step,attackerUnit,realEffectUnits,skillConfig,triggeredTalents);
		return realEffectUnits;
	}
	
	/**
	 * 
	 * @param skillConfig 
	 * @param reachUnits 
	 * @param attackerUnit 
	 * @param triggeredTalents 
	 * @return
	 */
	private List<FightSceneUnit> getSuckSkillRealEffectUnits(FightSceneUnit attackerUnit, List<FightSceneUnit> reachUnits, SkillConfig skillConfig) {
		List<FightSceneUnit> realEffectUnits = new ArrayList<>();
		Vector2 attackerPos = getTargetGridPos(attackerUnit.gridPos.getX(), attackerUnit.gridPos.getY());
		
		if(skillConfig.getAttackRangeType() == 1 ||
				skillConfig.getAttackRangeType() == 2 ||
				skillConfig.getAttackRangeType() == 3){
			for(FightSceneUnit fightSceneUnit : reachUnits){
				if(fightSceneUnit.unitType == EnumSceneUnitType.Monster.ordinal() 
						|| fightSceneUnit.unitType == EnumSceneUnitType.Player.ordinal()){
					Vector2 targetPos = getTargetGridPos(fightSceneUnit.gridPos.getX(), fightSceneUnit.gridPos.getY());
					Segment2 segment = new Segment2(attackerPos, targetPos);
					if(!testSegmentBlocked(segment,reachUnits)){
						realEffectUnits.add(fightSceneUnit);
					}
				}
			}
			//这之前的只有打到的人或怪
			for(FightSceneUnit fightSceneUnit : reachUnits){
				if(fightSceneUnit.unitType == EnumSceneUnitType.Obstacle.ordinal()){
					realEffectUnits.add(fightSceneUnit);
				}
			}
			return realEffectUnits;
		}else if(skillConfig.getAttackRangeType() == 4){//如果是子弹类型
			sortbyDistance(attackerUnit,reachUnits);
			if(reachUnits.size() > 0){
				FightSceneUnit targetFightSceneUnit = reachUnits.get(0);
				realEffectUnits.add(targetFightSceneUnit);
			}
		}else if(skillConfig.getAttackRangeType() == 0){
			realEffectUnits.addAll(reachUnits);
		}
		return realEffectUnits;
	}
	
	/**
	 * 无差别打到障碍物和人或怪
	 * @param step 
	 * @param fightUnit
	 * @param reachUnits
	 * @param skillConfig
	 * @param triggeredTalents
	 * @return
	 */
	private List<FightSceneUnit> allAttackSkillDeployEffect(BattleStep step, FightSceneUnit fightUnit, List<FightSceneUnit> reachUnits,
			SkillConfig skillConfig, List<Integer> triggeredTalents) {
		for(FightSceneUnit fightSceneUnit : reachUnits){
			int damage = calculateDamage(step,fightUnit,skillConfig,fightSceneUnit,triggeredTalents,((PlayerFightUnit)fightUnit).getSelectWeaponId(),deployStage);
			fightSceneUnit.deploySkillDamage = damage;
		}
		return reachUnits;
	}


	/**
	 * 部署阶段算伤害
	 * 要算上触发的天赋
	 * @param step 
	 * @param attackerUnit
	 * @param realEffectUnits
	 * @param skillConfig
	 * @param triggeredTalents
	 */
	private void deploySkill(BattleStep step, FightSceneUnit attackerUnit,
			List<FightSceneUnit> realEffectUnits, SkillConfig skillConfig, List<Integer> triggeredTalents) {
		for(FightSceneUnit fightSceneUnit : realEffectUnits){
			int damage = calculateDamage(step,attackerUnit,skillConfig,fightSceneUnit,triggeredTalents,((PlayerFightUnit)attackerUnit).getSelectWeaponId(),deployStage);
			fightSceneUnit.deploySkillDamage = damage;
		}
	}
	
	/**
	 * 
	 * @param step 
	 * @param attackerUnit
	 * @param skillConfig
	 * @param triggeredTalents (要计算触发的天赋)
	 * @param fightSceneUnit
	 * @return
	 * 单次攻击伤害 = （（攻击方攻击力计算结果 * （武器技能转化系数读技能表+ 属性伤害系数2016、2017、2018、2019 +伤害百分比加成2001、2002、2003、2004、2006）*（1-敌方防御免伤计算结果）+附加属性伤害读对应属性-属性抗性抵消读对应属性）* 属性相克/被克制伤害倍率计算结果 * 暴击伤害倍率计算结果 +附加额外伤害读技能表）
	 * 				*（1 + 攻击方伤害增加百分比1009– 受击方减伤百分比1010）
	 */
	private int calculateDamage(BattleStep step, FightSceneUnit attackerUnit,
			SkillConfig skillConfig, FightSceneUnit targetUnit, List<Integer> triggeredTalents,int weaponId,int stage) {
		//暴击伤害倍率
		float critValue = 100;
			
		//单次攻击伤害=[（攻防伤害 + 属性伤害）* 属性倍率 *暴击倍率 + 技能附加伤害值 ] * 整体伤害比率
		float attackDefenceDamage = 0;
		//先找出攻击是什么类型（穿刺，粉碎冲击等）
		int damageAttType = skillConfig.getDamageAttType();
		//敌方防御免伤
		float defenceDamage = 0;
		AttributeNumberConfig playerAttributeNumberConfig = XMLTemplateService.attributeNumberConfigMap.get(1);
		AttributeNumberConfig monsterAttributeNumberConfig = XMLTemplateService.attributeNumberConfigMap.get(2);
		//如果人是攻击者
		if(attackerUnit instanceof PlayerFightUnit){
			WeaponConfig weaponConfig = XMLTemplateService.weaponConfigMap.get(weaponId);
			attackDefenceDamage = (float)attackerUnit.getAttack() * (skillConfig.getConvertNum() + getAttrDamageRatio(attackerUnit,triggeredTalents,damageAttType)*0.01f
					+ getDamageAddPer(attackerUnit,triggeredTalents,weaponConfig)*0.01f);
			if(targetUnit.getDefence() != 0){
				defenceDamage = (float)targetUnit.getDefence() / (targetUnit.getDefence()*monsterAttributeNumberConfig.getDefRate() 
						+attackerUnit.getAttack()*playerAttributeNumberConfig.getDefIngore()+targetUnit.getLevel()*monsterAttributeNumberConfig.getDefLevelRate());
			}
			if(stage == realStage){
				float attackerCritRate = (float)attackerUnit.getCrit() / ( attackerUnit.getCrit()*playerAttributeNumberConfig.getCritRate() + attackerUnit.getLevel()*playerAttributeNumberConfig.getCritLevelRate());
				float targetTenRate = (float)targetUnit.getCrit() / ( targetUnit.getCrit()*monsterAttributeNumberConfig.getTenRate() +attackerUnit.getCrit()*playerAttributeNumberConfig.getTenIngore() + targetUnit.getLevel()*monsterAttributeNumberConfig.getTenLevelRate());
				int critRate = Math.min(75, (int)(5 + attackerCritRate*100 - targetTenRate*100));
				int random = RandomExt.getInstance().getRandom(101, true);
				if(random <= critRate){
					critValue = 100 + (float)attackerUnit.getCritDamage()*100 / 
							(attackerUnit.getCritDamage()* playerAttributeNumberConfig.getCritDamRate() + 
									playerAttributeNumberConfig.getCritDamWeight() +
									attackerUnit.getLevel()*playerAttributeNumberConfig.getCritDamLevelRate());
				}
			}else{
				critValue = 100;
			}
		}else{
			attackDefenceDamage = (float)attackerUnit.getAttack() * (skillConfig.getConvertNum() + getAttrDamageRatio(attackerUnit,triggeredTalents,damageAttType));
			defenceDamage = (float)targetUnit.getDefence() / (targetUnit.getDefence()*playerAttributeNumberConfig.getDefRate() 
					+attackerUnit.getAttack()*monsterAttributeNumberConfig.getDefIngore()+targetUnit.getLevel()*playerAttributeNumberConfig.getDefLevelRate());
			if(stage == realStage){
				float attackerCritRate = (float)attackerUnit.getCrit() / ( attackerUnit.getCrit()*monsterAttributeNumberConfig.getCritRate() + attackerUnit.getLevel()*monsterAttributeNumberConfig.getCritLevelRate());
				float targetTenRate = (float)targetUnit.getCrit() / ( targetUnit.getCrit()*playerAttributeNumberConfig.getCritRate() + attackerUnit.getCrit()*monsterAttributeNumberConfig.getTenIngore() + targetUnit.getLevel()*playerAttributeNumberConfig.getTenLevelRate());
				int critRate = Math.min(75, (int)(5 + attackerCritRate*100 - targetTenRate*100));
				int random = RandomExt.getInstance().getRandom(101, true);
				if(random <= critRate){
					critValue = 100 + (float)attackerUnit.getCritDamage()*100 / 
							(attackerUnit.getCritDamage()* monsterAttributeNumberConfig.getCritDamRate() + 
									monsterAttributeNumberConfig.getCritDamWeight() +
									attackerUnit.getLevel()*monsterAttributeNumberConfig.getCritDamLevelRate());
				}
			}else{
				critValue = 100;
			}
		}
		
		attackDefenceDamage = attackDefenceDamage * (1 - defenceDamage);
		
		
		//属性伤害=附加属性伤害读对应属性-属性抗性抵消读对应属性；
		float attrDamage = attackerUnit.getDamageAttrByType(damageAttType) - targetUnit.getDefenceAttrByType(damageAttType);
		//属性倍率(克制)
		float restrain = 1;
		int damageType = skillConfig.getDamageAttType();
		int armorType = targetUnit.getArmorType();
		int restrainId = damageType*10 + armorType;
		CounterConfig config = XMLTemplateService.counterConfigMap.get(restrainId);
		if(config != null){
			restrain = config.getNumber();
		}
		
		List<AttackAddEffect> addList = step.attackAddEffectsMap.get(targetUnit.getId());
		if(critValue > 100){
			if(addList == null){
				addList = new ArrayList<>();
				addList.add(AttackAddEffect.Crit);
				step.attackAddEffectsMap.put(targetUnit.getId(), addList);
			}else {
				addList.add(AttackAddEffect.Crit);
			}
		}
		//这里的是攻击者的克制 对于被攻击者的附加效果要反转一下
		if(restrain > 1){//被攻击者被克制
			if(addList == null){
				addList = new ArrayList<>();
				addList.add(AttackAddEffect.Restrain);
				step.attackAddEffectsMap.put(targetUnit.getId(), addList);
			}else {
				addList.add(AttackAddEffect.Restrain);
			}
		}else if(restrain < 1){
			if(addList == null){
				addList = new ArrayList<>();
				addList.add(AttackAddEffect.Restrained);
				step.attackAddEffectsMap.put(targetUnit.getId(), addList);
			}else {
				addList.add(AttackAddEffect.Restrained);
			}
		}
		//攻击方伤害增加百分比2009– 受击方减伤百分比2010
		float allDamageRatio = Math.max(0, getAddAllDamagePer(attackerUnit,triggeredTalents,damageAttType) - getAddAllDefencePer(attackerUnit,triggeredTalents,damageAttType));
		
		int damage = (int)(((attackDefenceDamage + attrDamage) * restrain * critValue*0.01f + skillConfig.getAddDamage() + getAddAllDamageValue(attackerUnit, triggeredTalents, damageAttType)) * (100+allDamageRatio)*0.01f);
		return (int)damage;
	}
	

	/**
	 * 获得属性伤害系数（天赋和buff共同作用）2016、2017、2018、2019 
	 * @param attackerUnit
	 * @param triggeredTalents
	 * @param damageAttType
	 * @return
	 * 
	 */
	private float getAttrDamageRatio(FightSceneUnit attackerUnit,
			List<Integer> triggeredTalents, int damageAttType) {
		float ratio = 0;
		List<HashMap<Integer,Integer>> effectList = new ArrayList<>();
		List<HashMap<Integer,Integer>> talentEffectList = getTalentEffect(triggeredTalents);
		effectList.addAll(talentEffectList);
		if(damageAttType == 1){//穿刺
			List<HashMap<Integer,Integer>> buffEffectList = attackerUnit.getBuffEffectListByType(BattleEnum.TalentEffect.ChuanCi.toNumber());
			effectList.addAll(buffEffectList);
			ratio = getEffectPerByType(BattleEnum.TalentEffect.ChuanCi.toNumber(),effectList);
		}else if(damageAttType == 2){//粉碎
			List<HashMap<Integer,Integer>> buffEffectList = attackerUnit.getBuffEffectListByType(BattleEnum.TalentEffect.FenSui.toNumber());
			effectList.addAll(buffEffectList);
			ratio = getEffectPerByType(BattleEnum.TalentEffect.FenSui.toNumber(),effectList);
		}else if(damageAttType == 3){//冲击
			List<HashMap<Integer,Integer>> buffEffectList = attackerUnit.getBuffEffectListByType(BattleEnum.TalentEffect.Chongji.toNumber());
			effectList.addAll(buffEffectList);
			ratio = getEffectPerByType(BattleEnum.TalentEffect.Chongji.toNumber(),effectList);
		}else if(damageAttType == 4){//切割
			List<HashMap<Integer,Integer>> buffEffectList = attackerUnit.getBuffEffectListByType(BattleEnum.TalentEffect.Qiege.toNumber());
			effectList.addAll(buffEffectList);
			ratio = getEffectPerByType(BattleEnum.TalentEffect.Qiege.toNumber(),effectList);
		}
		return ratio;
	}
	
	/**
	 * 获得武器相关的百分百加成（天赋和buff共同作用）2001、2002、2003、2004、2006
	 * @param attackerUnit
	 * @param triggeredTalents
	 * @param weaponConfig
	 * 1刀剑2枪3锤4盾5弓6匕首）
	 * @return
	 */
	private float getDamageAddPer(FightSceneUnit attackerUnit,
			List<Integer> triggeredTalents, WeaponConfig weaponConfig) {
		int weaponType = weaponConfig.getWeaponType();
		
		float ratio = 0;
		List<HashMap<Integer,Integer>> effectList = new ArrayList<>();
		List<HashMap<Integer,Integer>> talentEffectList = getTalentEffect(triggeredTalents);
		effectList.addAll(talentEffectList);
		if(weaponType == 1){
			List<HashMap<Integer,Integer>> weaponEffectList = attackerUnit.getBuffEffectListByType(BattleEnum.TalentEffect.DaoJianDamage.toNumber());
			effectList.addAll(weaponEffectList);
			ratio = getEffectPerByType(BattleEnum.TalentEffect.DaoJianDamage.toNumber(),effectList);
		}else if(weaponType == 2){
			List<HashMap<Integer,Integer>> weaponEffectList = attackerUnit.getBuffEffectListByType(BattleEnum.TalentEffect.QiangDamage.toNumber());
			effectList.addAll(weaponEffectList);
			ratio = getEffectPerByType(BattleEnum.TalentEffect.QiangDamage.toNumber(),effectList);
		}else if(weaponType == 3){
			List<HashMap<Integer,Integer>> weaponEffectList = attackerUnit.getBuffEffectListByType(BattleEnum.TalentEffect.ChuiDamage.toNumber());
			effectList.addAll(weaponEffectList);
			ratio = getEffectPerByType(BattleEnum.TalentEffect.ChuiDamage.toNumber(),effectList);
		}else if(weaponType == 5){
			List<HashMap<Integer,Integer>> weaponEffectList = attackerUnit.getBuffEffectListByType(BattleEnum.TalentEffect.NuDamage.toNumber());
			effectList.addAll(weaponEffectList);
			ratio = getEffectPerByType(BattleEnum.TalentEffect.NuDamage.toNumber(),effectList);
		}else if(weaponType == 6){
			List<HashMap<Integer,Integer>> weaponEffectList = attackerUnit.getBuffEffectListByType(BattleEnum.TalentEffect.BiShouDanage.toNumber());
			effectList.addAll(weaponEffectList);
			ratio = getEffectPerByType(BattleEnum.TalentEffect.BiShouDanage.toNumber(),effectList);
		}
		return ratio;
	}
	
	/**
	 * 获得最终伤害加成（（天赋和buff共同作用））2009
	 * @param attackerUnit
	 * @param triggeredTalents
	 * @param damageAttType
	 * @return
	 */
	private float getAddAllDamagePer(FightSceneUnit attackerUnit,List<Integer> triggeredTalents, int damageAttType) {
		float ratio = 0;
		List<HashMap<Integer,Integer>> effectList = new ArrayList<>();
		List<HashMap<Integer,Integer>> talentEffectList = getTalentEffect(triggeredTalents);
		effectList.addAll(talentEffectList);
		
		List<HashMap<Integer,Integer>> weaponEffectList = attackerUnit.getBuffEffectListByType(BattleEnum.TalentEffect.AllAttackDamage.toNumber());
		effectList.addAll(weaponEffectList);
		ratio = getEffectPerByType(BattleEnum.TalentEffect.AllAttackDamage.toNumber(),effectList);
		return ratio;
	}
	
	/**
	 * 获得最终伤害加成（（天赋和buff共同作用））1009
	 * @param attackerUnit
	 * @param triggeredTalents
	 * @param damageAttType
	 * @return
	 */
	private float getAddAllDamageValue(FightSceneUnit attackerUnit,List<Integer> triggeredTalents, int damageAttType) {
		float ratio = 0;
		List<HashMap<Integer,Integer>> effectList = new ArrayList<>();
		List<HashMap<Integer,Integer>> talentEffectList = getTalentEffect(triggeredTalents);
		effectList.addAll(talentEffectList);
		
		List<HashMap<Integer,Integer>> weaponEffectList = attackerUnit.getBuffEffectListByType(BattleEnum.TalentEffect.AllAttackDamage.toNumber());
		effectList.addAll(weaponEffectList);
		ratio = getEffectValueByType(BattleEnum.TalentEffect.AllAttackDamage.toNumber(),effectList);
		return ratio;
	}

	/**
	 * 获得最终防御加成（天赋和buff共同作用）2010
	 * @param attackerUnit
	 * @param triggeredTalents
	 * @param damageAttType
	 * @return
	 */
	private float getAddAllDefencePer(FightSceneUnit attackerUnit,List<Integer> triggeredTalents, int damageAttType) {
		float ratio = 0;
		List<HashMap<Integer,Integer>> effectList = new ArrayList<>();
		List<HashMap<Integer,Integer>> talentEffectList = getTalentEffect(triggeredTalents);
		effectList.addAll(talentEffectList);
		
		List<HashMap<Integer,Integer>> weaponEffectList = attackerUnit.getBuffEffectListByType(BattleEnum.TalentEffect.AllDefenceDamage.toNumber());
		effectList.addAll(weaponEffectList);
		ratio = getEffectPerByType(BattleEnum.TalentEffect.AllDefenceDamage.toNumber(),effectList);
		return ratio;
	}

	/**
	 * 根据类型属性获取效果的百分百数值(暂时只考虑1000到3000的)
	 * @param ordinal
	 * @param effectList 
	 * @return
	 */
	private float getEffectPerByType(int type, List<HashMap<Integer, Integer>> effectList) {
		float effectPer = 0;
		for(HashMap<Integer, Integer> map : effectList){
			for(Entry<Integer,Integer> entry : map.entrySet()){
				if(entry.getKey() % 1000 == type && entry.getKey() / 1000 == 2){
					effectPer += entry.getValue();
				}
			}
		}
		return effectPer;
	}

	/**
	 * 根据类型属性获取效果的数值(type 效果是1000到3000 时 type为余数)
	 * @param effectList 
	 * @return
	 */
	private float getEffectValueByType(int type, List<HashMap<Integer, Integer>> effectList) {
		float effectValue = 0;
		for(HashMap<Integer, Integer> map : effectList){
			for(Entry<Integer,Integer> entry : map.entrySet()){
				if(entry.getKey() % 1000 == type && entry.getKey() / 1000 == 1){
					effectValue += entry.getValue();
				}
			}
		}
		
		return effectValue;
	}


	/**
	 * 根据触发的天赋id取得生效的天赋效果
	 * @param triggeredTalents
	 * @return
	 */
	public List<HashMap<Integer, Integer>> getTalentEffect(List<Integer> triggeredTalents){
		List<HashMap<Integer,Integer>> effectList = new ArrayList<>();
		if(triggeredTalents != null){
			for(Integer talentId : triggeredTalents){
				TalentEffectConfig talentEffectConfig = XMLTemplateService.tallentEffectConfigMap.get(talentId);
				if(talentEffectConfig != null){
					String effectId = talentEffectConfig.getEffectid();
					String[] effectParam = effectId.split(",");
					int id = Integer.valueOf(effectParam[0]);
					int count = Integer.valueOf(effectParam[1]);
					HashMap<Integer, Integer> effectMap = new HashMap<>();
					effectMap.put(id, count);
					effectList.add(effectMap);
				}
			}
		}
		return effectList;
	}
	
	/**
	 * 判断线上是否有阻挡物
	 * @param segment
	 * @param reachUnits
	 */
	private boolean testSegmentBlocked(Segment2 segment,
			List<FightSceneUnit> reachUnits) {
		boolean blocked = false;
		for(FightSceneUnit unit : reachUnits){
			if(unit.unitType == EnumSceneUnitType.Obstacle.ordinal()){
				blocked = ColidTest.testSegment2Box2(segment, getTargetGrid(unit.gridPos.getX(), unit.gridPos.getY()).gridBox2);
				if(blocked){
					return blocked;
				}
			}
		}
		
		return blocked;
	}

	public class DistanceCompartor implements Comparator<FightSceneUnit>{

		@Override
		public int compare(FightSceneUnit o1, FightSceneUnit o2) {
			
			return o1.getTargetDistance() - o2.getTargetDistance();
		}
		
	}

	private void sortbyDistance(FightSceneUnit fightUnit,
			List<FightSceneUnit> reachUnits) {
		for(FightSceneUnit unit : reachUnits){
			unit.targetFightUnit = fightUnit;
		}
		
		Collections.sort(reachUnits, new DistanceCompartor());
		
		for(FightSceneUnit unit : reachUnits){
			unit.targetFightUnit = null;
		}
	}
	
	/**
	 * 根据部署阶段的结果 （主要是选择的目标路线等） 执行真正的结果
	 * @param step
	 * @param attackCount 
	 * @return
	 */
	public BattleStep takeRealEffect(BattleStep step, int attackCount) {
		List<FightSceneUnit> realEffectUnits = getRealEffectUnitsByDeployUnits(step.effectUnits);
		List<FightSceneUnit> realEffectCloneUnits = new ArrayList<>();
		SkillConfig skillConfig = XMLTemplateService.skillConfigMap.get(step.skillId);
		if(step.stepType == BattleStepType.Attact){
			FightSceneUnit stepAttackerUnit = step.attacker;
			FightSceneUnit attackerUnit = null;
			for(FightSceneUnit player : getPlayers(realStage).values()){
				if(player.getId() == stepAttackerUnit.getId()){
					attackerUnit = player;
					break;
				}
			}
			//叠加次数的天赋
			List<Integer> triggeredAddTalents = checkRealTimeTriggerAddTalents((PlayerFightUnit)attackerUnit,step.weaponCfgId);
			//连击的天赋 中间可以夹杂行走 上盾其他逻辑
			List<Integer> triggeredSeriAttackTalents = checkRealTimeTriggerSeriAttackTalents((PlayerFightUnit)attackerUnit,attackCount,step.weaponCfgId);
			FightSceneUnit tarentEnemy = getEnemyById(step.targetId, realStage);
			List<Integer> triggeredAttackTarTalents = null;
			if(tarentEnemy != null){
				triggeredAttackTarTalents = checkRealTimeTriggerAttackTarTalents((PlayerFightUnit)attackerUnit,tarentEnemy,step.weaponCfgId);
			}
			List<Integer> triggeredTalents = new ArrayList<>();
			
			triggeredTalents.addAll(triggeredAddTalents);
			triggeredTalents.addAll(triggeredSeriAttackTalents);
			if(triggeredAttackTarTalents != null){
				triggeredTalents.addAll(triggeredAttackTarTalents);
			}
			
			for(FightSceneUnit fightSceneUnit : realEffectUnits){
				int singleRoundTotalDamage = 0;
				if(stepAttackerUnit.getId() != fightSceneUnit.getId()){
					int damage = calculateDamage(step,attackerUnit,skillConfig,fightSceneUnit,triggeredTalents,step.weaponCfgId,realStage);
					fightSceneUnit.takeRealEffect_damage(damage);
					if (fightSceneUnit.getUnitType() != EnumSceneUnitType.Obstacle.ordinal()) {
						singleRoundTotalDamage += damage;
					}
				}
				this.achievementService.checkAchievement(AchievementType.TotalRoundsDamage, this.unitIdToAccountMap.get(attackerUnit.getId()), Integer.toString(singleRoundTotalDamage));
				this.achievementService.checkAchievement(AchievementType.SingleRoundDamage, this.unitIdToAccountMap.get(attackerUnit.getId()), Integer.toString(singleRoundTotalDamage));
			}
			checkTalentsAddBuff(attackerUnit,realEffectUnits,triggeredTalents);
			checkAddBuff(attackerUnit, skillConfig, realEffectUnits);
			for(FightSceneUnit fightSceneUnit : realEffectUnits){
				realEffectCloneUnits.add(fightSceneUnit.clone());
			}
			step.effectUnits = realEffectCloneUnits;
			attackerUnit.gridPos = stepAttackerUnit.gridPos;
			
		}else if(step.stepType == BattleStepType.Search){
			FightSceneUnit attackerUnit = step.attacker;
			for(FightSceneUnit player : getPlayers(realStage).values()){
				if(player.getId() == attackerUnit.getId()){
					player.gridPos = attackerUnit.gridPos;
					realEffectCloneUnits.add(attackerUnit.clone());
					break;
				}
			}
			step.effectUnits = realEffectCloneUnits;
		}else if(step.stepType == BattleStepType.UseShield){
			FightSceneUnit attackerUnit = step.attacker;
			FightSceneUnit attacker = null;
			if(attackerUnit != null){
				for(FightSceneUnit player : getPlayers(realStage).values()){
					if(player.getId() == attackerUnit.getId()){
						attacker = player;
						break;
					}
				}
				if(attacker != null){
					checkAddBuff(attacker, skillConfig, realEffectUnits);
					for(FightSceneUnit fightSceneUnit : realEffectUnits){
						Shield shield = new Shield();
						int power = (int)(fightSceneUnit.getAttack()*skillConfig.getConvertNum()+skillConfig.getAddShield());
						shield.setTotalPower(power);
						shield.setCurrentPower(power);
						fightSceneUnit.setShield(shield);
						realEffectCloneUnits.add(fightSceneUnit.clone());
					}
					step.effectUnits = realEffectCloneUnits;
				}
				
			}
		}
		return step;
	}

	


	private List<FightSceneUnit> getRealEffectUnitsByDeployUnits(List<FightSceneUnit> deployEffectUnits) {
		List<FightSceneUnit> realEffectUnits = new ArrayList<>();
		List<FightSceneUnit> monsters = sceneObjs.get(EnumSceneUnitType.Monster.ordinal());
		if(monsters != null){
			for(FightSceneUnit unit : monsters){
				if(deployEffectUnits.contains(unit)){
					realEffectUnits.add(unit);
				}
			}	
		}
		
		List<FightSceneUnit> obstacles = sceneObjs.get(EnumSceneUnitType.Obstacle.ordinal());
		if(obstacles != null){
			for(FightSceneUnit unit : sceneObjs.get(EnumSceneUnitType.Obstacle.ordinal())){
				if(deployEffectUnits.contains(unit)){
					realEffectUnits.add(unit);
				}
			}
		}
		
		for(FightSceneUnit player : getPlayers(realStage).values()){
			if(deployEffectUnits.contains(player)){
				realEffectUnits.add(player);
			}
		}
		
		return realEffectUnits;
	}
	
	/**
	 * 怪物开始行动
	 * @return
	 */
	public List<BattleStep> monsterAction() {
		List<BattleStep> monsterSteps = new ArrayList<>();
		//先是人打机器人 后是机器人打人
		List<MonsterFightUnit> enemyUnits = getMonsters(BattleMap.realStage);
		int size = enemyUnits.size();
		for(int i=0; i < size; i++){
			MonsterFightUnit monster = (MonsterFightUnit)enemyUnits.get(i);
			//执行之前判断是否为激活状态
			if(!monster.isActive()){
				checkMonsterActive(monster);
			}
			if(monster.isActive()){
				monterAI(monsterSteps,monster);
			}
		}
		return monsterSteps;
	}
	
	/**
	 * 检测怪物是否被激活
	 * @param monster
	 */
	private void checkMonsterActive(MonsterFightUnit monster) {
		for(FightSceneUnit playerUnit : getAlivePlayers(realStage)){
			if(getUnitsDistance(playerUnit,monster) < monster.getScanRange()){
				monster.setActive(true);
				monster.setActiveRound(battleRound);
			}
		}
	}


	/**
	 * 怪物执行AI
	 * @param monsterSteps
	 * @param monster
	 */
	private void monterAI(List<BattleStep> monsterSteps, MonsterFightUnit monster) {
		if(monster.getCurrentHp() <= 0 && monster.isJustDead() == false){
			return;
		}
//		List<Integer> aiList = ((MonsterFightUnit)monster).getAiList();
		List<MonsterAI> aiList = monster.getAiList();
		for(MonsterAI monsterAi : aiList){
			if(!monsterAi.isActive()){
				checkAiActive(monster,monsterAi);
			}
			if(!monsterAi.isActive()){
				continue;
			}
			//如果变身了 当回合的ai就不继续放了
			if(monster.isTransformed() && battleRound == monster.getTransformRound()){
				break;
			}
			AiConfig aiConfig = XMLTemplateService.aiConfigMap.get(monsterAi.getId());
			//先判断cd是否转好
			if(aiConfig.getIntervalRound() != 0 && (battleRound - monsterAi.getLastActionRound() < aiConfig.getIntervalRound())){
				continue;
			}
			//如果执行次数达到上限
			if(monsterAi.getActionCount() >= aiConfig.getUseCount()){
				continue;
			}
			
			List<String> events = aiConfig.getEventList();
			boolean eventsReached = checkAiEventsReached(events,(MonsterFightUnit)monster);
			//如果条件都达成 再判断行为执行类型 是依次执行 还是按概率执行一个
			if(eventsReached){
				//1.依次执行100%触发
				if(aiConfig.getActionType() == 1){
					List<Integer> actionList = aiConfig.getActionList();
					for(Integer actionId : actionList){
						AiActionConfig aiActionConfig = XMLTemplateService.aiActionConfigMap.get(actionId);
						FightSceneUnit targetUnit = getTargrtByType(monster,aiActionConfig.getTarget());
//						if(targetUnit != null && targetUnit.getCurrentHp() > 0){
						if(targetUnit != null){
							takeAiAction(monster,monsterSteps,aiActionConfig,targetUnit,monsterAi);
						}
					}
				}else if(aiConfig.getActionType() == 2){//如果是按概率触发的
					List<Integer> actionList = aiConfig.getActionList();
					List<Integer> actionRates = aiConfig.getActionRateList();
					int weight = 0;
					for(Integer rate : actionRates){
						weight += rate;
					}
					int randRate = RandomExt.getInstance().getRandom(weight, true);
					int i = 0;
					weight = 0;
					for(Integer rate : actionRates){
						weight += rate;
						if(randRate < weight){
							break;
						}
						i++;
					}
					int actionId = actionList.get(i);
					AiActionConfig aiActionConfig = XMLTemplateService.aiActionConfigMap.get(actionId);
					FightSceneUnit targetUnit = getTargrtByType(monster,aiActionConfig.getTarget());
					if(targetUnit != null && targetUnit.getCurrentHp() > 0){
						takeAiAction(monster,monsterSteps,aiActionConfig,targetUnit,monsterAi);
					}
				}
			}
		}
		
		if(monster.isTransformed() && battleRound == monster.getTransformRound()){
			monster.updateAI();;
		}
	}
	
	/**
	 * 检测ai是否激活(此时怪物已经激活)
	 * @param monster 
	 * @param monsterAi
	 */
	private void checkAiActive(MonsterFightUnit monster, MonsterAI monsterAi) {
		AiConfig aiConfig = XMLTemplateService.aiConfigMap.get(monsterAi.getId());
		if(aiConfig.getStartFireRound() == 0){
			monsterAi.setActive(true);
		}else {
			if(monsterAi.getLastCheckActiveRound() < battleRound){
				monsterAi.setLastCheckActiveRound(battleRound);
				if(battleRound-monster.getActiveRound() >= aiConfig.getStartFireRound()){
					monsterAi.setActive(true);
				}
			}
		}
	}


	/**
	 * 执行AI的行为
	 * @param aiActionConfig
	 * @param targetUnit
	 * @param monsterAi 
	 * @param breakAilist 
	 */
	private void takeAiAction(MonsterFightUnit monster,List<BattleStep> monsterSteps,AiActionConfig aiActionConfig,
			FightSceneUnit targetUnit, MonsterAI monsterAi) {
		if(targetUnit == null){
			return;
		}
		//此处有多个action 如果是有次数限制的ai 执行一个就要记次
		List<String> actionList = aiActionConfig.getActionList();
		//用来记录执行成功的ai次数
		int actionCount = 0;
		for(String action : actionList){
			String[] actionParam = action.split(",");
			int actionType = Integer.parseInt(actionParam[0]);
			switch (actionType) {
				//像目标移动
				case AiConst.actionId1:
					if(moveToTargetAI(monsterAi,monsterSteps,monster,targetUnit,Integer.parseInt(actionParam[1]))){
						actionCount++;
					}
					break;
				case AiConst.actionId2:
					break;
				case AiConst.actionId3:
					break;
				//释放技能
				case AiConst.actionId4:
					if(useSkillAI(monsterAi,monsterSteps,monster,targetUnit,Integer.parseInt(actionParam[1]),Integer.parseInt(actionParam[2]))){
						actionCount++;
					}
					break;
				//像目标移动并释放技能
				case AiConst.actionId5:
					if(moveAndUseSkillAI(monsterAi,monsterSteps,monster,targetUnit,Integer.parseInt(actionParam[1]),Integer.parseInt(actionParam[2]))){
						actionCount++;
					}
					break;
				case AiConst.actionId6:
				//增加buff
					int buffId6 = Integer.parseInt(actionParam[1]);
					targetUnit.addBuff(monster, buffId6);
					actionCount++;
					break;
				case AiConst.actionId7:
				//删除buff
					int buffId7 = Integer.parseInt(actionParam[1]);
					targetUnit.removeBuff(buffId7);
					actionCount++;
					break;
				case AiConst.actionId8:
					break;
				case AiConst.actionId9:
					break;
			default:
				break;
			}
		}
		
		if(actionCount > 0){
			monsterAi.setLastActionRound(battleRound);
			monsterAi.addActionCount();
		}
	}
	
	/**
	 * 释放技能
	 * @param monsterAi 
	 * @param monsterSteps
	 * @param monster
	 * @param targetUnit
	 * @param skillId
	 * @param count 释放次数
	 * @param breakAilist 
	 */
	private boolean useSkillAI(MonsterAI monsterAi, List<BattleStep> monsterSteps,
			MonsterFightUnit monster, FightSceneUnit targetUnit, int skillId,int count) {
		SkillConfig skillConfig = XMLTemplateService.skillConfigMap.get(skillId);
		int actionCost = skillConfig.getConsumePower();
		for(int i = 0; i<count ; i++){
			if(monster.getCurrentActionPower() < actionCost){
				return false;
			}
			monster.costActionPower(actionCost);
			
			GridPosition gridPosition = monster.gridPos;
			BattleStep step = new BattleStep();
			step.startPos = monster.gridPos;
//			step.endPos = monster.gridPos;
			step.targetId = targetUnit.getId();
			if(skillConfig.getSkillType() == EnumSkillType.Teleport.ordinal()){
				List<GridPosition> emptyGridPositions = getNeighborEmptyGrids(targetUnit.gridPos.getX(),
						targetUnit.gridPos.getY(), (int)skillConfig.getRadius(), realStage);
				Collections.shuffle(emptyGridPositions);
				int emptyGridCount = emptyGridPositions.size();
				if(emptyGridCount == 0){
					return false;
				}
				
				List<PathNode> pathNodeList = new ArrayList<>();
				PathNode startPathNode = new PathNode(false, null, monster.gridPos.getX(), monster.gridPos.getY());
				pathNodeList.add(startPathNode);
				
				monster.gridPos = emptyGridPositions.get(0);
				PathNode endPathNode = new PathNode(false, null, monster.gridPos.getX(), monster.gridPos.getY());
				pathNodeList.add(endPathNode);
				updateGridDatas(realStage);
				
				step.searchPathNodes = null;
				step.teleportPathNodes = pathNodeList;
				step.skillId = skillId;
				step.attacker = monster.clone();
				step.stepType = BattleStepType.Teleport;
				monsterSteps.add(step);
			}
			else if(skillConfig.getSkillType() == EnumSkillType.Summon.ordinal()){
				List<GridPosition> emptyGridPositions = getNeighborEmptyGrids(targetUnit.gridPos.getX(),
						targetUnit.gridPos.getY(), (int)skillConfig.getRadius(), realStage);
				Collections.shuffle(emptyGridPositions);
				int emptyGridCount = emptyGridPositions.size();
				if(emptyGridCount == 0){
					return false;
				}
				
				int summonIndex = 0;
				String summonUnits = skillConfig.getSunmmonUnits();//格式是 1001,2|2001,3
				if(summonUnits==null || "".equals(summonUnits)){
					return false;
				}
				String[] summonParams = summonUnits.split("\\|");
				for(int j = 0; j<summonParams.length; j++){
					String[] summonItems = summonParams[j].split(",");
					int monsterId = Integer.valueOf(summonItems[0]);
					int summonCount = Integer.valueOf(summonItems[1]);
					
					if(summonIndex >= emptyGridCount){
						return false;
					}
					for(int m=0; m<summonCount; m++){
						GridPosition position = emptyGridPositions.get(summonIndex);
						MonsterFightUnit monsterFightUnit = new MonsterFightUnit(monsterId,position.getX(),position.getY(),null);
						List<FightSceneUnit> sceneUnits = sceneObjs.get(EnumSceneUnitType.Monster.ordinal());
						sceneUnits.add(monsterFightUnit);
						step.summonUnits.add(monsterFightUnit);
						summonIndex++;
					}
				}
				updateGridDatas(realStage);
				step.searchPathNodes = null;
				step.skillId = skillId;
				step.attacker = monster.clone();
				step.stepType = BattleStepType.Summon;
				monsterSteps.add(step);
			}
			else if(skillConfig.getSkillType() == EnumSkillType.Transform.ordinal()){
				monster.setCfgId(skillConfig.getTransformId());
				monster.setTransformed(true);
				monster.setTransformRound(battleRound);
				List<FightSceneUnit> reachCloneUnits = new ArrayList<>();
				reachCloneUnits.add(monster.clone());
				step.searchPathNodes = null;
				step.skillId = skillId;
				step.attacker = monster.clone();
				step.effectUnits = reachCloneUnits;
				step.stepType = BattleStepType.Transform;
				monsterSteps.add(step);
			}
			else if(skillConfig.getSkillType() == EnumSkillType.AddBuff.ordinal()){
				List<FightSceneUnit> reachUnits = useSkill(skillConfig,false, getTargetGridPos(gridPosition.getX(), gridPosition.getY()),
						getTargetGridPos(targetUnit.gridPos.getX(),targetUnit.gridPos.getY()), targetUnit,
						EnumAttackRangeType.values()[skillConfig.getAttackRangeType()],BattleMap.realStage);
				if(reachUnits == null || reachUnits.size() == 0){
					return false;
				}
				List<FightSceneUnit> realUnits = new ArrayList<>();
				if(skillConfig.getThroughObType() == 1){
					realUnits = getSuckSkillRealEffectUnits(monster, reachUnits, skillConfig);
				}else if(skillConfig.getThroughObType() == 2){
					realUnits = reachUnits;
				}else if(skillConfig.getThroughObType() == 3){
					realUnits = getIgnoreSkillRealEffectUnits(monster, reachUnits, skillConfig);
				}else if(skillConfig.getThroughObType() == 4){
					realUnits = reachUnits;
				}
				
				List<FightSceneUnit> reachCloneUnits = new ArrayList<>();
				checkAddBuff(monster, skillConfig, realUnits);
				for(FightSceneUnit unit : realUnits){
					reachCloneUnits.add(unit.clone());
				}
				if(!reachCloneUnits.contains(monster)){
					reachCloneUnits.add(monster.clone());
				}
				
				step.searchPathNodes = null;
				step.effectUnits = reachCloneUnits;
				step.skillId = skillId;
				step.attacker = monster.clone();
				step.stepType = BattleStepType.AddBuff;
				
				monsterSteps.add(step);
			}
			else{
				List<FightSceneUnit> reachUnits = useSkill(skillConfig,false, getTargetGridPos(gridPosition.getX(), gridPosition.getY()),
						getTargetGridPos(targetUnit.gridPos.getX(),targetUnit.gridPos.getY()), targetUnit,
						EnumAttackRangeType.values()[skillConfig.getAttackRangeType()],BattleMap.realStage);
				if(reachUnits == null || reachUnits.size() == 0){
					return false;
				}
				List<FightSceneUnit> realUnits = new ArrayList<>();
				if(skillConfig.getThroughObType() == 1){
					realUnits = getSuckSkillRealEffectUnits(monster, reachUnits, skillConfig);
				}else if(skillConfig.getThroughObType() == 2){
					realUnits = reachUnits;
				}else if(skillConfig.getThroughObType() == 3){
					realUnits = getIgnoreSkillRealEffectUnits(monster, reachUnits, skillConfig);
				}else if(skillConfig.getThroughObType() == 4){
					realUnits = reachUnits;
				}
				
				List<FightSceneUnit> reachCloneUnits = new ArrayList<>();
				
				for(FightSceneUnit unit : realUnits){
					if(skillConfig.getSkillType() == EnumSkillType.Heal.ordinal()){
						int heal = (int)(monster.getAttack()* skillConfig.getConvertNum());
						unit.takeRealEffect_heal(heal);
						reachCloneUnits.add(unit.clone());
					}else if(skillConfig.getSkillType() == EnumSkillType.Damage.ordinal()){
						int damage = calculateDamage(step,monster,skillConfig,unit,null,0,realStage);
						unit.takeRealEffect_damage(damage);
						reachCloneUnits.add(unit.clone());
					}else if(skillConfig.getSkillType() == EnumSkillType.Shield.ordinal()){
						Shield shield = new Shield();
						int power = (int)(monster.getAttack()*skillConfig.getConvertNum()+skillConfig.getAddShield());
						shield.setTotalPower(power);
						shield.setCurrentPower(power);
						unit.setShield(shield);
						reachCloneUnits.add(unit.clone());
					}
				}
				checkAddBuff(monster, skillConfig, realUnits);
				if(!reachCloneUnits.contains(monster)){
					reachCloneUnits.add(monster.clone());
				}
				step.searchPathNodes = null;
				step.effectUnits = reachCloneUnits;
				step.skillId = skillId;
				step.attacker = monster.clone();
				
				monsterSteps.add(step);
			}
		}
		updateGridDatas(BattleMap.realStage);
//		monsterAi.setLastActionRound(battleRound);
//		monsterAi.addActionCount();
		return true;
	}

	/**
	 * 检查技能是否受障碍物影响
	 * @param skillConfig
	 * @return
	 */
	public boolean checkIgnoreObstacle(SkillConfig skillConfig) {
		
		if(skillConfig.getThroughObType() == 1){
			return false;
		}else if(skillConfig.getThroughObType() == 2 
				||skillConfig.getThroughObType() == 3 || skillConfig.getThroughObType() == 4){
			return true;
		}
		return true;
	}
	
	/**
	 * 
	 * @param monsterAi 
	 * @param monsterSteps
	 * @param monster
	 * @param targetUnit
	 * @param range 攻击距离
	 */
	private boolean moveToTargetAI(MonsterAI monsterAi, List<BattleStep> monsterSteps,
			FightSceneUnit monster, FightSceneUnit targetUnit, int range) {
		//技能是否受障碍物影响
		boolean ignoreObstacle = false;
//		GridPosition gridPosition = autoSearchGrid(ignoreObstacle, monster.gridPos.getX(), monster.gridPos.getY(),
//				new Vector2(targetUnit.gridPos.getX(),targetUnit.gridPos.getY()), BattleEnum.EnumAttackRangeType.Circle, range,realStage);
//		if(gridPosition == null){
//			return false;
//		}else{
//			System.out.println("怪物最佳攻击点为:"+gridPosition.getX()+ " " + gridPosition.getY());
//		}

		GridPosition gridPosition = null;
		List<PathNode> list = search(ignoreObstacle, monster.gridPos.getX(),monster.gridPos.getY(),
				targetUnit.gridPos.getX(),targetUnit.gridPos.getY(), range, targetUnit.getRadius());
		
		if((list!=null)&&(list.size()>0)) {
			//如果获取到最佳路径，则最佳路径的最后一个离怪物最近的点即是最佳攻击点。
			gridPosition= new GridPosition(list.get(list.size()-1).getX(), list.get(list.size()-1).getY());
			System.out.println("怪物最佳攻击点为:" + gridPosition.getX()+ " " + gridPosition.getY());
		}else{
			return false;
		}
		
		List<PathNode> realList = new ArrayList<>();
		int realCost = 0;
		
		int actionCost = (list.size()-1) * monster.getMoveCap();
		if(monster.getCurrentActionPower() < actionCost){
			int canMoveCount = monster.getCurrentActionPower()/monster.getMoveCap();
			if(canMoveCount <= 0){
				return false;
			}
			for(int i =0 ; i<canMoveCount ;i++){
				realList.add(list.get(i));
			}
			PathNode lastNode = realList.get(realList.size()-1);
			gridPosition = new GridPosition(lastNode.getX(), lastNode.getY());
			realCost = canMoveCount * monster.getMoveCap();
		}else{
			realList = list;
			realCost = actionCost;
		}
			
		monster.costActionPower(realCost);
		BattleStep step = new BattleStep();
		step.startPos = monster.gridPos;
		monster.gridPos = gridPosition;
		step.endPos = monster.gridPos;
		step.targetId = targetUnit.getId();
		step.searchType = 2;
		
		step.searchPathNodes = realList;
		step.skillId = 0;
		step.attacker = monster.clone();
		
		monsterSteps.add(step);
		updateGridDatas(BattleMap.realStage);
		
//		monsterAi.setLastActionRound(battleRound);
//		monsterAi.addActionCount();
		return true;
	}
	
	/**
	 * 向目标移动并释放技能(只有ai调用)
	 * @param monsterAi 
	 * @param monsterSteps
	 * @param monster
	 * @param targetUnit
	 * @param aiActionConfig
	 * @param count 释放次数
	 */
	private boolean moveAndUseSkillAI(MonsterAI monsterAi, List<BattleStep> monsterSteps,
			FightSceneUnit monster, FightSceneUnit targetUnit,
			int skillId,int count) {
		SkillConfig skillConfig = XMLTemplateService.skillConfigMap.get(skillId);
		//技能是否受障碍物影响
		boolean ignoreObstacle = checkIgnoreObstacle(skillConfig);
//		GridPosition gridPosition = autoSearchGrid(ignoreObstacle, monster.gridPos.getX(), monster.gridPos.getY(),
//				new Vector2(targetFightSceneUnit.gridPos.getX(),targetFightSceneUnit.gridPos.getY()), EnumAttackRangeType.values()[skillConfig.getAttackRangeType()], skillConfig.getMaxDist(),realStage);
//		if(gridPosition == null){
//			return false;
//		} else{
//			System.out.println("怪物最佳攻击点为:"+gridPosition.getX()+ " " + gridPosition.getY());
//		}

		GridPosition gridPosition = null;
		List<PathNode> list = search(ignoreObstacle, monster.gridPos.getX(),monster.gridPos.getY(),
				targetUnit.gridPos.getX(),targetUnit.gridPos.getY(), skillConfig.getMaxDist(), targetUnit.getRadius());
		
		if((list!=null)&&(list.size()>0)) {
			//如果获取到最佳路径，则最佳路径的最后一个离怪物最近的点即是最佳攻击点。
			gridPosition= new GridPosition(list.get(list.size()-1).getX(), list.get(list.size()-1).getY());
			System.out.println("怪物最佳攻击点为:" + gridPosition.getX()+ " " + gridPosition.getY());
		}else{
			return false;
		}
		
		int moveCost = (list.size()-1) * monster.getMoveCap();
		int skillCost = skillConfig.getConsumePower();
		
		int actionCost = moveCost + skillCost;
		if(monster.getCurrentActionPower() < actionCost){
			return false;
		}
		
		monster.costActionPower(actionCost);
		BattleStep step = new BattleStep();
		step.startPos = monster.gridPos;
		monster.gridPos = gridPosition;
		step.endPos = monster.gridPos;
		step.targetId = targetUnit.getId();
		
		List<FightSceneUnit> reachUnits = useSkill(skillConfig,false, getTargetGridPos(gridPosition.getX(), gridPosition.getY()),
				getTargetGridPos(targetUnit.gridPos.getX(),targetUnit.gridPos.getY()), targetUnit,
				EnumAttackRangeType.values()[skillConfig.getAttackRangeType()],BattleMap.realStage);
		
		List<FightSceneUnit> realUnits = new ArrayList<>();
		if(skillConfig.getThroughObType() == 1){
			realUnits = getSuckSkillRealEffectUnits(monster, reachUnits, skillConfig);
		}else if(skillConfig.getThroughObType() == 2){
			realUnits = reachUnits;
		}else if(skillConfig.getThroughObType() == 3){
			realUnits = getIgnoreSkillRealEffectUnits(monster, reachUnits, skillConfig);
		}else if(skillConfig.getThroughObType() == 4){
			realUnits = reachUnits;
		}
		
		List<FightSceneUnit> reachCloneUnits = new ArrayList<>();
		
		for(FightSceneUnit unit : realUnits){
			if(skillConfig.getSkillType() == EnumSkillType.Heal.ordinal()){
				int heal = (int)(monster.getAttack()* skillConfig.getConvertNum());
				unit.takeRealEffect_heal(heal);
				reachCloneUnits.add(unit.clone());
			}else if(skillConfig.getSkillType() == EnumSkillType.Damage.ordinal()){
				int damage = calculateDamage(step,monster,skillConfig,unit,null,0,realStage);
				unit.takeRealEffect_damage(damage);
				reachCloneUnits.add(unit.clone());
			}else if(skillConfig.getSkillType() == EnumSkillType.Shield.ordinal()){
				Shield shield = new Shield();
				int power = (int)(monster.getAttack()*skillConfig.getConvertNum()+skillConfig.getAddShield());
				shield.setTotalPower(power);
				shield.setCurrentPower(power);
				unit.setShield(shield);
				reachCloneUnits.add(unit.clone());
			}
		}
		checkAddBuff(monster, skillConfig, realUnits);
		if(!reachCloneUnits.contains(monster)){
			reachCloneUnits.add(monster.clone());
		}
		
		step.searchPathNodes = list;
		step.effectUnits = reachCloneUnits;
		step.skillId = skillId;
		step.attacker = monster.clone();
		
		monsterSteps.add(step);
		
		//看剩下的行动力还够不够放技能
		if(count - 1 > 0){
			for(int i=0 ;i< count -1;i++){
				if(monster.getCurrentActionPower() < skillCost){
					return false;
				}
				monster.costActionPower(skillCost);
				
				BattleStep battleStep = new BattleStep();
				battleStep.startPos = monster.gridPos;
				battleStep.endPos = monster.gridPos;
				battleStep.targetId = targetUnit.getId();
				
				List<FightSceneUnit> reachUnits1 = useSkill(skillConfig,false, getTargetGridPos(gridPosition.getX(), gridPosition.getY()),
						getTargetGridPos(targetUnit.gridPos.getX(),targetUnit.gridPos.getY()), targetUnit,
						EnumAttackRangeType.values()[skillConfig.getAttackRangeType()],BattleMap.realStage);
				
				List<FightSceneUnit> realUnits1 = new ArrayList<>();
				if(skillConfig.getThroughObType() == 1){
					realUnits = getSuckSkillRealEffectUnits(monster, reachUnits1, skillConfig);
				}else if(skillConfig.getThroughObType() == 2){
					realUnits = reachUnits1;
				}else if(skillConfig.getThroughObType() == 3){
					realUnits = getIgnoreSkillRealEffectUnits(monster, reachUnits1, skillConfig);
				}else if(skillConfig.getThroughObType() == 4){
					realUnits = reachUnits;
				}
				List<FightSceneUnit> reachCloneUnits1 = new ArrayList<>();
				
				for(FightSceneUnit unit : realUnits1){
					if(skillConfig.getSkillType() == EnumSkillType.Heal.ordinal()){
						int heal = (int)(monster.getAttack()* skillConfig.getConvertNum());
						unit.takeRealEffect_heal(heal);
						reachCloneUnits1.add(unit.clone());
					}else if(skillConfig.getSkillType() == EnumSkillType.Damage.ordinal()){
						int damage = calculateDamage(step,monster,skillConfig,unit,null,0,realStage);
						unit.takeRealEffect_damage(damage);
						reachCloneUnits1.add(unit.clone());
					}else if(skillConfig.getSkillType() == EnumSkillType.Shield.ordinal()){
						Shield shield = new Shield();
						int power = (int)(monster.getAttack()*skillConfig.getConvertNum()+skillConfig.getAddShield());
						shield.setTotalPower(power);
						shield.setCurrentPower(power);
						unit.setShield(shield);
						reachCloneUnits1.add(unit.clone());
					}
				}
				
				battleStep.searchPathNodes = null;
				battleStep.effectUnits = reachCloneUnits1;
				battleStep.skillId = skillId;
				battleStep.attacker = monster.clone();
				
				monsterSteps.add(battleStep);
			}
		}
		
		updateGridDatas(BattleMap.realStage);
//		monsterAi.setLastActionRound(battleRound);
//		monsterAi.addActionCount();
		return true;
	}

	private FightSceneUnit getTargrtByType(FightSceneUnit monster,String target) {
		FightSceneUnit targetUnit = null;
		List<MonsterFightUnit> monsters = getMonsters(realStage);
		String[] targetParam = target.split(",");
		int targetType = Integer.parseInt(targetParam[0]);
		switch (targetType) {
			case AiConst.targetId1:
				break;
			//找血量最低的目标
			case AiConst.targetId2:
				int targetRelation = Integer.parseInt(targetParam[1]);
				int minHp = Integer.MAX_VALUE;
				FightSceneUnit minHpUnit = null;
				//如果是敌方
				if(targetRelation == 1){
					for(FightSceneUnit playerUnit : getPlayers(realStage).values()){
						if(playerUnit.getCurrentHp() > 0 && playerUnit.getCurrentHp() < minHp){
							minHp = playerUnit.getCurrentHp();
							minHpUnit = playerUnit;
						}
					}
					targetUnit = minHpUnit;
				}else {//是友方的情况
					for(FightSceneUnit monsterUnit : monsters){
						if(monsterUnit.getCurrentHp() > 0 && monsterUnit.getCurrentHp() < minHp){
							minHp = monsterUnit.getCurrentHp();
							minHpUnit = monsterUnit;
						}
					}
					targetUnit = minHpUnit;
				}
				
				break;
			//找血量最高的目标
			case AiConst.targetId3:
				int targetRelation3 = Integer.parseInt(targetParam[1]);
				int maxHp = 0;
				FightSceneUnit maxHpUnit = null;
				//如果是敌方
				if(targetRelation3 == 1){
					for(FightSceneUnit playerUnit : getPlayers(realStage).values()){
						if(playerUnit.getCurrentHp() > 0 && playerUnit.getCurrentHp() > maxHp){
							maxHp = playerUnit.getCurrentHp();
							maxHpUnit = playerUnit;
						}
					}
					targetUnit = maxHpUnit;
				}else {//是友方的情况
					for(FightSceneUnit monsterUnit : monsters){
						if(monsterUnit.getCurrentHp() > 0 && monsterUnit.getCurrentHp() > maxHp){
							maxHp = monsterUnit.getCurrentHp();
							maxHpUnit = monsterUnit;
						}
					}
					targetUnit = maxHpUnit;
				}
				break;
			//直线距离最近的目标
			case AiConst.targetId4:
				float minDistance = Float.MAX_VALUE;
				FightSceneUnit minDistanceUnit = null;
				
				int targetRelation4 = Integer.parseInt(targetParam[1]);
				if(targetRelation4 == 1){
					for(FightSceneUnit playerUnit : getPlayers(realStage).values()){
						if(playerUnit.getCurrentHp() < 0){
							continue;
						}
						if(getUnitsDistance(playerUnit,monster) < minDistance){
							minDistance = getUnitsDistance(playerUnit,monster);
							minDistanceUnit = playerUnit;
						}
					}
					targetUnit = minDistanceUnit;
				}else{
					for(FightSceneUnit monsterUnit : monsters){
						if(getUnitsDistance(monster,monsterUnit) < minDistance){
							minDistance = getUnitsDistance(monster,monsterUnit);
							minDistanceUnit = monsterUnit;
						}
					}
					targetUnit = minDistanceUnit;
				}
				
				break;
			case AiConst.targetId5:
				float maxDistance = 0;
				FightSceneUnit maxDistanceUnit = null;
				
				int targetRelation5 = Integer.parseInt(targetParam[1]);
				if(targetRelation5 == 1){
					for(FightSceneUnit playerUnit : getPlayers(realStage).values()){
						if(playerUnit.getCurrentHp() < 0){
							continue;
						}
						if(getUnitsDistance(playerUnit,monster) > maxDistance){
							maxDistance = getUnitsDistance(playerUnit,monster);
							maxDistanceUnit = playerUnit;
						}
					}
					targetUnit = maxDistanceUnit;
				}else {
					for(FightSceneUnit monsterUnit : monsters){
						if(getUnitsDistance(monster,monsterUnit) > maxDistance){
							maxDistance = getUnitsDistance(monster,monsterUnit);
							maxDistanceUnit = monsterUnit;
						}
					}
					targetUnit = maxDistanceUnit;
				}
				
				break;
			//自身
			case AiConst.targetId6:
				targetUnit = monster;
				break;
			//特定目标id 配置id
			case AiConst.targetId7:
				int targetCfgId = Integer.parseInt(targetParam[1]);
				for(FightSceneUnit monsterUnit : monsters){
					if(monsterUnit.getCurrentHp() > 0 && ((MonsterFightUnit)monsterUnit).getCfgId() == targetCfgId){
						targetUnit = monsterUnit;
						break;
					}
				}
				break;
			case AiConst.targetId8:
				break;
			case AiConst.targetId9:
				break;
			case AiConst.targetId10:
				break;
			case AiConst.targetId11:
				break;
			case AiConst.targetId12:
				break;
			case AiConst.targetId13:
				break;
			case AiConst.targetId14:
				break;
			case AiConst.targetId15:
			//获得指定buff的目标
				int targetRelation15 = Integer.parseInt(targetParam[1]);
				int buffId15 = Integer.parseInt(targetParam[2]);
				if(targetRelation15 == 1){
					List<PlayerFightUnit> playerFightUnits = getAlivePlayers(realStage);
					for(PlayerFightUnit playerFightUnit : playerFightUnits){
						if(playerFightUnit.getBuffCountById(buffId15) > 0){
							targetUnit = playerFightUnit;
							break;
						}
					}
				}else if(targetRelation15 == 2){
					List<MonsterFightUnit> monsterFightUnits = getAliveMonsters(realStage);
					for(MonsterFightUnit monsterFightUnit : monsterFightUnits){
						if(monsterFightUnit.getBuffCountById(buffId15) > 0){
							targetUnit = monsterFightUnit;
							break;
						}
					}
				}else if(targetRelation15 == 3){
					List<PlayerFightUnit> playerFightUnits = getAlivePlayers(realStage);
					List<MonsterFightUnit> monsterFightUnits = getAliveMonsters(realStage);
					List<FightSceneUnit> aliveUnits = new ArrayList<>();
					aliveUnits.addAll(playerFightUnits);
					aliveUnits.addAll(monsterFightUnits);
					for(FightSceneUnit fightUnit : aliveUnits){
						if(fightUnit.getBuffCountById(buffId15) > 0){
							targetUnit = fightUnit;
							break;
						}
					}
				}
				break;
			case AiConst.targetId16:
			//没有指定buff的目标
				int targetRelation16 = Integer.parseInt(targetParam[1]);
				int buffId16 = Integer.parseInt(targetParam[2]);
				if(targetRelation16 == 1){
					List<PlayerFightUnit> playerFightUnits = getAlivePlayers(realStage);
					for(PlayerFightUnit playerFightUnit : playerFightUnits){
						if(playerFightUnit.getBuffCountById(buffId16) <= 0){
							targetUnit = playerFightUnit;
							break;
						}
					}
				}else if(targetRelation16 == 2){
					List<MonsterFightUnit> monsterFightUnits = getAliveMonsters(realStage);
					for(MonsterFightUnit monsterFightUnit : monsterFightUnits){
						if(monsterFightUnit.getBuffCountById(buffId16) <= 0){
							targetUnit = monsterFightUnit;
							break;
						}
					}
				}else if(targetRelation16 == 3){
					List<PlayerFightUnit> playerFightUnits = getAlivePlayers(realStage);
					List<MonsterFightUnit> monsterFightUnits = getAliveMonsters(realStage);
					List<FightSceneUnit> aliveUnits = new ArrayList<>();
					aliveUnits.addAll(playerFightUnits);
					aliveUnits.addAll(monsterFightUnits);
					for(FightSceneUnit fightUnit : aliveUnits){
						if(fightUnit.getBuffCountById(buffId16) <= 0){
							targetUnit = fightUnit;
							break;
						}
					}
				}
				break;
			case AiConst.targetId17:
				int targetRelation17 = Integer.parseInt(targetParam[1]);
				if(targetRelation17 == 1){
					List<PlayerFightUnit> playerFightUnits = getAlivePlayers(realStage);
					for(PlayerFightUnit player : playerFightUnits){
						if(player.getShield() != null){
							targetUnit = player;
							break;
						}
					}
				}else if(targetRelation17 == 2){
					List<MonsterFightUnit> monsterFightUnits = getAliveMonsters(realStage);
					for(MonsterFightUnit monsterFightUnit : monsterFightUnits){
						if(monsterFightUnit.getShield() != null){
							targetUnit = monsterFightUnit;
							break;
						}
					}
				}
				break;
			case AiConst.targetId18:
				int targetRelation18 = Integer.parseInt(targetParam[1]);
				if(targetRelation18 == 1){
					List<PlayerFightUnit> playerFightUnits = getAlivePlayers(realStage);
					for(PlayerFightUnit player : playerFightUnits){
						if(player.getShield() == null){
							targetUnit = player;
							break;
						}
					}
				}else if(targetRelation18 == 2){
					List<MonsterFightUnit> monsterFightUnits = getAliveMonsters(realStage);
					for(MonsterFightUnit monsterFightUnit : monsterFightUnits){
						if(monsterFightUnit.getShield() == null){
							targetUnit = monsterFightUnit;
							break;
						}
					}
				}
				break;
			//周围有设定数量的敌方单位的目标
			case AiConst.targetId19:
				int radius = Integer.parseInt(targetParam[1]);
				int minNum = Integer.parseInt(targetParam[2]);
				int maxNum = Integer.parseInt(targetParam[3]);
				
				List<PlayerFightUnit> players = getAlivePlayers(realStage);
				HashMap<PlayerFightUnit,Integer> playerNeighborCountMap = new HashMap<>();
				
				for(PlayerFightUnit player : players){
					int count = 0;
					List<GridPosition> neighborGrids = getNeighborGrids(player.gridPos.getX(), player.gridPos.getY(), radius);
					for(PlayerFightUnit player1 : players){
						if(player.getId() == player1.getId()){
							continue;
						}
						if(neighborGrids.contains(player1.gridPos)){
							count++;
						}
					}
					playerNeighborCountMap.put(player, count);
				}
				for (Entry<PlayerFightUnit, Integer> entry : playerNeighborCountMap.entrySet()) {
					if(entry.getValue() > minNum && entry.getValue() <= maxNum){
						targetUnit = entry.getKey();
						break;
					}
				}
				
				break;
			//随机目标1、敌方 2、友方  3、全部
			case AiConst.targetId20:
				int targetRelation20 = Integer.parseInt(targetParam[1]);
				if(targetRelation20 == 1){
					List<PlayerFightUnit> playerFightUnits = getAlivePlayers(realStage);
					int size = playerFightUnits.size();
					if(size > 0){
						int index = RandomExt.getInstance().getRandom(0, size-1);
						targetUnit = playerFightUnits.get(index);
					}
				}else if(targetRelation20 == 2){
					List<MonsterFightUnit> monsterFightUnits = getAliveMonsters(realStage);
					List<MonsterFightUnit> monstersNotIncludeSelf = new ArrayList<>();
					for(MonsterFightUnit monsterFightUnit : monsterFightUnits){
						if(monsterFightUnit.getId() != monster.getId()){
							monstersNotIncludeSelf.add(monsterFightUnit);
						}
					}
					int size = monstersNotIncludeSelf.size();
					if(size > 0){
						int index = RandomExt.getInstance().getRandom(0, size-1);
						targetUnit = monstersNotIncludeSelf.get(index);
					}
				}else if(targetRelation20 == 3){
					List<PlayerFightUnit> playerFightUnits = getAlivePlayers(realStage);
					List<MonsterFightUnit> monsterFightUnits = getAliveMonsters(realStage);
					List<FightSceneUnit> aliveUnits = new ArrayList<>();
					for(MonsterFightUnit monsterFightUnit : monsterFightUnits){
						if(monsterFightUnit.getId() != monster.getId()){
							aliveUnits.add(monsterFightUnit);
						}
					}
					aliveUnits.addAll(playerFightUnits);
					
					int size = aliveUnits.size();
					if(size > 0){
						int index = RandomExt.getInstance().getRandom(0, size-1);
						targetUnit = aliveUnits.get(index);
					}
				}
				break;
			//血量最低的友方目标（按百分比判断，并排除100%和0%血）
			case AiConst.targetId21:
				float minHpPer = 1;
				FightSceneUnit minHpPerUnit = null;
				for(FightSceneUnit monsterUnit : monsters){
					if(monsterUnit.getCurrentHp() > 0 && monsterUnit.getCurrentHp() != monsterUnit.getTotalHp() && (float)monsterUnit.getCurrentHp()/monsterUnit.getTotalHp() < minHpPer){
						minHpPer = (float)monsterUnit.getCurrentHp()/monsterUnit.getTotalHp();
						minHpPerUnit = monsterUnit;
					}
				}
				targetUnit = minHpPerUnit;
				break;
			case AiConst.targetId22:
				float maxHpPer = 0;
				FightSceneUnit maxHpPerUnit = null;
				for(FightSceneUnit monsterUnit : monsters){
					if(monsterUnit.getCurrentHp() > 0 && monsterUnit.getCurrentHp() != 0 && (float)monsterUnit.getCurrentHp()/monsterUnit.getTotalHp() > maxHpPer){
						maxHpPer = (float)monsterUnit.getCurrentHp()/monsterUnit.getTotalHp();
						maxHpPerUnit = monsterUnit;
					}
				}
				targetUnit = maxHpPerUnit;
				break;
			default:
				break;
		}
		return targetUnit;
	}
	
	/**
	 * 获取两个战斗单元的距离
	 * @param unit1
	 * @param unit2
	 * @return
	 */
	private float getUnitsDistance(FightSceneUnit unit1,FightSceneUnit unit2) {
		Vector2 posVector1 = new Vector2(unit1.gridPos.getX(),unit1.gridPos.getY());
		Vector2 posVector2 = new Vector2(unit2.gridPos.getX(),unit2.gridPos.getY());
		Vector2 forwardVector2 = Vector2.sub(posVector1, posVector2);
		float length = forwardVector2.getMagnitude();
		return length;
	}
	
	/**
	 * 获取两个坐标距离
	 * @param pos1
	 * @param pos2
	 * @return
	 */
	public float getVectorDistance(Vector2 pos1,Vector2 pos2){
		Vector2 forwardVector2 = Vector2.sub(pos1, pos2);
		float length = forwardVector2.sqrMagnitude();
		return length;
	}

	private boolean checkAiEventsReached(List<String> events,MonsterFightUnit monster) {
		if(events.size() == 0 && monster.getCurrentHp() > 0){
			return true;
		}
		boolean conditionReach = false;
		for(String event : events){
			String[] eArray = event.split(",");
			int eventId = Integer.valueOf(eArray[0]);
			
			switch (eventId) {
				//自己死亡
				case AiConst.eventId1:
					if(monster.getCurrentHp() <= 0 && monster.isJustDead()){
						conditionReach = true;
					}
					break;
				case AiConst.eventId2:
					break;
				case AiConst.eventId3:
					break;
				case AiConst.eventId4:
					//自身血量达到一个百分百范围
					int minHp = (int)(Integer.valueOf(eArray[1])*monster.getTotalHp()*0.01f);
					int maxHp = (int)(Integer.valueOf(eArray[2])*monster.getTotalHp()*0.01f);
					if(monster.getCurrentHp() > minHp && monster.getCurrentHp() <= maxHp){
						conditionReach = true;
					}else {
						conditionReach = false;
						return false;
					}
					break;
				case AiConst.eventId5:
					break;
				case AiConst.eventId6:
					break;
				case AiConst.eventId7:
					break;
				case AiConst.eventId8:
					break;
				case AiConst.eventId9:
					break;
				case AiConst.eventId10:
					break;
				case AiConst.eventId11:
					break;
				case AiConst.eventId12:
					//特定BUFF的叠加层数范围
					int buffId = Integer.valueOf(eArray[1]);
					int minNum = Integer.valueOf(eArray[2]);
					int maxNum = Integer.valueOf(eArray[3]);
					int buffCount = monster.getBuffCountById(buffId);
					
					if(buffCount > minNum && buffCount <= maxNum){
						conditionReach = true;
					}
					break;
				case AiConst.eventId13:
					//战场上存在的特定BUFF的数量范围
					int buffId13 = Integer.valueOf(eArray[1]);
					int minNum13 = Integer.valueOf(eArray[2]);
					int maxNum13 = Integer.valueOf(eArray[3]);
					int buffCount13 = 0;
					
					List<PlayerFightUnit> players = getAlivePlayers(realStage);
					List<MonsterFightUnit> monsters = getAliveMonsters(realStage);
					
					for(PlayerFightUnit player : players){
						buffCount13 += player.getBuffCountById(buffId13);
					}
					for(MonsterFightUnit monsterUnit : monsters){
						buffCount13 += monsterUnit.getBuffCountById(buffId13);
					}
					
					if(buffCount13 > minNum13 && buffCount13 <= maxNum13){
						conditionReach = true;
					}
					break;
					
				default:
					break;
				}
		}
		return conditionReach;
	}
	
	/**
	 * 根据不同阶段更新地图数据	
	 */
	@SuppressWarnings("unchecked")
	public void updateMapByStage(int mapIndex) {
//		String step = "";
//		if(stage == 1){
//			step = battleMapItemConfig.getStep1();
//		}else if(stage == 2){
//			step = battleMapItemConfig.getStep2();
//		}else {
//			step = battleMapItemConfig.getStep3();
//		}
		
//		if(step == null || "".equals(step)){
//			return;
//		}
		ObjectMapper mapper = new ObjectMapper();
		JsonNode node;
		try {
			
			
			node = mapper.readTree(battleMapItemConfig.getGrids());
			String datasJson = node.get("list").toString();
			List<GridDatas> gridDatasConfigList;
			gridDatasConfigList = (ArrayList<GridDatas>)mapper.readValue(datasJson, new TypeReference<List<GridDatas>>(){});
			GridDatas gDatas = gridDatasConfigList.get(mapIndex);
			
//			GridDatas gridConfigDatas = new GridDatas();
//			String widthString = node.get("width").toString();
//			String heightString = node.get("height").toString();
//			gridConfigDatas.width = Integer.parseInt(widthString);
//			gridConfigDatas.height = Integer.parseInt(heightString);
//			String datasJson = node.get("list").toString();
//			List<GridData> datas;
//			datas = (ArrayList<GridData>)mapper.readValue(datasJson, new TypeReference<List<GridData>>(){});
//			gridConfigDatas.datas = datas;
			
			this.playerBornPosList = new ArrayList<>();
			this.gridDatas = gDatas;
			grids = new Grid[gridDatas.width][gridDatas.height];
			this.gridWidthNum = gridDatas.height;
			this.gridHeightNum = gridDatas.width;
			int count = 0;
			for (int x = 0; x < gridDatas.width; x++){
				for (int y = 0; y < gridDatas.height; y++)
				{
					GridData gridData = gridDatas.datas.get(count);
					grids[x][y] = new Grid(gridData.X,gridData.Y,gridData.IsWall,gridData.pos);
					count++;
				}
			}
			initGridObjects(gridDatas);
			
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 检测是否更新游戏地图阶段
	 * 返回结果true为游戏结束 false为还没结束
	 * @param res 
	 */
	public int checkMapChangeStageOrGameOver(BWStartBattleRES.Builder res) {
		boolean allMonsterDead = true;
		boolean allPlayersDead = true;
		int playerDeadCount  = 0;	
		for(PlayerFightUnit playerFightUnit : getPlayers(realStage).values()){
			if(playerFightUnit.getCurrentHp() > 0){
				allPlayersDead = false;
				setDungeonConditionUnits(PlayerLiveReachRounds,battleRound+"");
				setDungeonConditionUnits(PlayersOverRoundsCount,battleRound+"");
				
				List<MonsterFightUnit> allMonsters = getMonsters(realStage);
				for(MonsterFightUnit monster : allMonsters){
					if(monster.isJustDead()) {
						this.achievementService.checkAchievement(AchievementType.SingleRoundKillMonsterCount, this.unitIdToAccountMap.get(playerFightUnit.getId()), Integer.toString(monster.getCfgId()));
					}
				}
			}else {
				playerDeadCount ++;
			}
		}
		
		if(allPlayersDead) {//游戏结束
			MGameOver.Builder gameOverBuidlder = MGameOver.newBuilder();
			gameOverBuidlder.setResult(2);
			res.setGameOverInfo(gameOverBuidlder);
			//游戏结束失败，不向客户端推送副本掉落物品的数据
			setDungeonConditionUnits(AllPlayersFailed,"");
			return -1;
		}
	
		List<MonsterFightUnit> monsters = getMonsters(realStage);
		for(MonsterFightUnit monster : monsters){
			if(monster.getCurrentHp() > 0){
				allMonsterDead = false;
			}else if(monster.isJustDead()) {
				//有怪物死了，增加怪物掉落代码，向客户端推送怪物掉落的随机物品数据
				DropItem dropItem = GetDropItem(monster);
				if(dropItem != null) {
					res.addMonsterDropItems(dropItem.toProto());
				}
				setDungeonConditionUnits(KillBossMonster, monster.getCfgId()+"") ;
			}
		}
	
		if(allMonsterDead){
			setDungeonConditionUnits(KillAllMonster,"");
		}
		
		if(!isBattleStepOver(battleStep)) {
			return 0;//战斗没有结束返回继续战斗
		}
		
		if(isBattleOverSuccess()) {
			// 看是否有下一阶段
			int nextStage = currentStage + 1;
			int gridIndex = -1;
			String step = "";
			if (nextStage == 2) {
				step = mapLevelItemConfig.getStep2();
				gridIndex = mapLevelItemConfig.getStap2GridIndex();
				battleStep = 2;
			} else if (nextStage == 3) {
				step = mapLevelItemConfig.getStep3();
				gridIndex = mapLevelItemConfig.getStap3GridIndex();
				battleStep = 3;
			}
			if (!"".equals(step)) {
				//战斗阶段结束，进入下一场景战斗
				currentStage = nextStage;
				updateMapByStage(gridIndex);
				updateGridDatasByLevelCfg(currentStage);
				MStageInfo.Builder stageInfoBuilder = MStageInfo.newBuilder();
				stageInfoBuilder.setStage(currentStage);
				stageInfoBuilder.setMapIndex(gridIndex);
				int bornIndex = 0;
				for (String account : playerOperList) {
					PlayerFightUnit playerFightSceneUnit = (PlayerFightUnit) players.get(account);
					playerFightSceneUnit.clearAllBuffs();
					playerFightSceneUnit.gridPos = new GridPosition(playerBornPosList.get(bornIndex).NodeX,	playerBornPosList.get(bornIndex).NodeY);
					// FightUnitInfo.Builder uintInfo = FightUnitInfo.newBuilder();
					// uintInfo.setAccount(account);
					// uintInfo.setId(playerFightSceneUnit.getId());
					// if(playerFightSceneUnit.equals(roomOwner)){
					// uintInfo.setRoleType(1);
					// playerFightSceneUnit.gridPos = new
					// GridPosition(playerBornPosList.get(0).NodeX, playerBornPosList.get(0).NodeY);
					// }else {
					// uintInfo.setRoleType(0);
					// playerFightSceneUnit.gridPos = new
					// GridPosition(playerBornPosList.get(1).NodeX, playerBornPosList.get(1).NodeY);
					// }
					//
					// playerFightSceneUnit.setInitWeaponId(playerFightSceneUnit.getSelectWeaponId());
					// MPathNode.Builder posNode = MPathNode.newBuilder();
					// posNode.setX(playerFightSceneUnit.gridPos.getX());
					// posNode.setY(playerFightSceneUnit.gridPos.getY());
					// uintInfo.setPos(posNode);
					// uintInfo.setCurrentHp(playerFightSceneUnit.getCurrentHp());
					// uintInfo.setTotalHp(playerFightSceneUnit.getTotalHp());
					//
					// uintInfo.setSelectedWeapon(playerFightSceneUnit.getSelectWeaponId());
					// MWeaponInfo.Builder weaponInfo = MWeaponInfo.newBuilder();
					// weaponInfo.setWeaponId(playerFightSceneUnit.getSelectWeaponId());
					// uintInfo.setWeaponInfo(weaponInfo);
	
					stageInfoBuilder.addFightUnits(playerFightSceneUnit.toProto());
					bornIndex++;
				}
				List<MonsterFightUnit> enemys = getMonsters(BattleMap.deployStage);
				if (enemys != null) {
					for (FightSceneUnit enemy : enemys) {
						stageInfoBuilder.addEnemyObstacles(enemy.toProto());
					}
				}
				List<FightSceneUnit> obstacles = getObstacles(BattleMap.deployStage);
				if (obstacles != null) {
					for (FightSceneUnit obstacle : obstacles) {
						stageInfoBuilder.addEnemyObstacles(obstacle.toProto());
					}
				}
				res.setStageInfo(stageInfoBuilder);
				return 0;
				//战斗阶段结束成功返回进行下一个阶段的战斗
			}	
			else {
				for(PlayerFightUnit playerFightUnit : getPlayers(realStage).values()){
					if(playerFightUnit.getCurrentHp() > 0){//经策划确认，死人不给奖励
						this.achievementService.checkAchievement(AchievementType.BattleRound, this.unitIdToAccountMap.get(playerFightUnit.getId()), Integer.toString(battleRound));
						this.achievementService.checkAchievement(AchievementType.SelfHPPercent, this.unitIdToAccountMap.get(playerFightUnit.getId()), Integer.toString(playerFightUnit.getCurrentHp()*100/playerFightUnit.getTotalHp()));
						this.achievementService.checkAchievement(AchievementType.TeamPlayerDeadCount, this.unitIdToAccountMap.get(playerFightUnit.getId()), Integer.toString(playerDeadCount));
						List<MonsterFightUnit> allMonsters = getMonsters(realStage);
						for(MonsterFightUnit monster : allMonsters){
							if(monster.isJustDead()) {
								this.achievementService.checkAchievement(AchievementType.TotalRoundsKillMonsterCount, this.unitIdToAccountMap.get(playerFightUnit.getId()), Integer.toString(monster.getCfgId()));
								this.achievementService.checkAchievement(AchievementType.KillSpecificMonster, this.unitIdToAccountMap.get(playerFightUnit.getId()), Integer.toString(monster.getCfgId()));
							}
						}
					}
				}
				
				HashMap<String, HashMap<String, String>> retPlayerAchievementItems = achievementService.settleAchievementReward();
				for (String account : retPlayerAchievementItems.keySet()) {
					HashMap<String, String> retPlayerAchievementItem = retPlayerAchievementItems.get(account);
					List<ItemEntity> itemEntityList = new ArrayList<>();
					for (String item : retPlayerAchievementItem.keySet()) {
						int itemId = Integer.parseInt(item);
						int itemCnt = Integer.parseInt(retPlayerAchievementItem.get(item));
						ItemEntity itemEntity = new ItemEntity();
						itemEntity.setItemId(itemId);
						itemEntity.setCount(itemCnt);
						itemEntityList.add(itemEntity);
					}
					playerAchievementItems.put(account, itemEntityList);
				}
				
				return 1;//战斗任务结束成功返回
			}
		}
		return -1;//战斗任务结束失败返回
	}
	
	public boolean isBattleStepOver(int battlestep){
		boolean ret = false;
		ConcurrentHashMap<Integer, ConditionUnit> dungeonConditionUnits = null;
		if(battlestep == 1) {
			dungeonConditionUnits = dungeonConditionUnits1;
		}else if(battlestep == 2) {
			dungeonConditionUnits = dungeonConditionUnits2;
		}else if(battlestep == 3) {
			dungeonConditionUnits = dungeonConditionUnits3;
		}
		for(Entry<Integer, ConditionUnit> conditionUnitMap : dungeonConditionUnits.entrySet()) {
			ConditionUnit conditionUnit = conditionUnitMap.getValue();
			if (conditionUnit.getStatus() == 1) {
				ret = true;
			}
		}
		return ret;
	}

	public boolean isBattleOverSuccess(){
		boolean ret = true;
		if(battleStep == 1) {
			ret = isBattleStepOverSuccess(dungeonConditionUnits1);
		}else if(battleStep == 2) {
			ret = isBattleStepOverSuccess(dungeonConditionUnits1)
					&&isBattleStepOverSuccess(dungeonConditionUnits2);
		}else if(battleStep == 3) {
			ret = isBattleStepOverSuccess(dungeonConditionUnits1)
					&&isBattleStepOverSuccess(dungeonConditionUnits2)
					&&isBattleStepOverSuccess(dungeonConditionUnits3);
		}
		return ret;
	}
	
	public boolean isBattleStepOverSuccess(ConcurrentHashMap<Integer, ConditionUnit> dungeonConditionUnits){
		boolean ret = true;
		for(Entry<Integer, ConditionUnit> conditionUnitMap : dungeonConditionUnits.entrySet()) {
			ConditionUnit conditionUnit = conditionUnitMap.getValue();
			boolean step = true;
			if(conditionUnit.getType() < 200) {
				if(conditionUnit.getStatus() == 0) {
					step = false;
				}
			}else {
				if(conditionUnit.getStatus() == 1) {
					step = false;
				}
			}
			ret = ret&&step;
		}
		return ret;
	}
	
	public void setDungeonConditionUnits(int type, String condition) {
		ConcurrentHashMap<Integer, ConditionUnit> dungeonConditionUnits = null;
		if(battleStep == 1) {
			dungeonConditionUnits = dungeonConditionUnits1;
		}
		else if(battleStep == 2) {
			dungeonConditionUnits = dungeonConditionUnits2;
		}
		else if(battleStep == 3) {
			dungeonConditionUnits = dungeonConditionUnits3;
		}
		
		for (Entry<Integer, ConditionUnit> conditionUnitMap : dungeonConditionUnits.entrySet()) {
			int id = conditionUnitMap.getKey();
			ConditionUnit conditionUnit = conditionUnitMap.getValue();
			if(type != conditionUnit.getType()) {
				continue;
			}
			if ((type == AllPlayersFailed) || (type == KillAllMonster)) {
				conditionUnit.setStatus(1);
				dungeonConditionUnits.put(id, conditionUnit);
				continue;
			}
			else if (type == KillBossMonster) {
				String bossMonsters = conditionUnit.getCondition();
				if((bossMonsters!=null) && (!bossMonsters.isEmpty())) {
					for(String monster:bossMonsters.split(",")) {
						if((monster!=null) && (!monster.isEmpty())) {
						int monsterId = Integer.parseInt(monster);
						int bossMonsterId = Integer.parseInt(condition);
						if (monsterId == bossMonsterId) {
							conditionUnit.setStatus(1);
							dungeonConditionUnits.put(id, conditionUnit);
						}
						}
					}
				}
				continue;
			}
			else if((type == PlayerLiveReachRounds)
					||(type == NpcLiveReachRounds)
					||(type == PlayersOverRoundsCount)) {
				int roundCnt = Integer.parseInt(conditionUnit.getCondition());
				int battleRound = Integer.parseInt(condition);
				if (battleRound >= roundCnt) {
					conditionUnit.setStatus(1);
					dungeonConditionUnits.put(id, conditionUnit);
				}
				continue;
			}
			else if (type == GotoSpecifiedPoint) {
				continue;
			} 
			else if (type == EscortTargetSuccess) {
				continue;
			} 
			else if (type == EscortTargetFailed) {
				continue;
			}
		}
	}
	
	public DropItem GetDropItem(MonsterFightUnit monster) {
		DropItem dropItem = new DropItem(monster.getId());
		String drops = monster.getDrops();
		if((drops!=null) && (!drops.isEmpty())) {
			String[] dropItems = drops.split("\\|");
			for(String dropItemStr : dropItems) {
				int dropId = Integer.parseInt(dropItemStr.split(",")[0]);
				int times = Integer.parseInt(dropItemStr.split(",")[1]);
				for(int index =0 ; index<times; index++) {
					DropItemConfig dropItemConfig = XMLTemplateService.dropItemConfigMap.get(dropId);
					if(dropItemConfig!=null) {
						int type = dropItemConfig.getType();
						String content = dropItemConfig.getContent();
						String[] items = content.split("\\|");
						if(type == 1) {
							for(String item :items) {
								int itemId = Integer.parseInt(item.split(",")[0]);
								int itemCnt = Integer.parseInt(item.split(",")[1]);
								ItemEntity itemEntity = new ItemEntity();
								itemEntity.setItemId(itemId);
								itemEntity.setCount(itemCnt);
								dropItem.addItemInfo(itemEntity);
								ItemEntity itemEntity1 = null;
								if(monstersDropItems.containsKey(itemId)) {
									itemEntity1 = monstersDropItems.get(itemId);
								}
								if(itemEntity1 != null) {
									itemEntity1.setCount(itemEntity.getCount() + itemEntity1.getCount());
									monstersDropItems.put(itemId, itemEntity1);
								}else {
									monstersDropItems.put(itemId, itemEntity);
								}
							}
						}else {
							List<ProbabilityGift> gifts = new ArrayList<ProbabilityGift>();		 
							int itemIndex = 0;
							for(String item :items) {
								String itemId = item.split(",")[0];
								String itemCnt = item.split(",")[1];
								double itemGv = Double.parseDouble(item.split(",")[2]);
								//序号==物品Id==物品数量==概率	
								gifts.add(new ProbabilityGift(itemIndex, itemId, itemCnt, itemGv));
								itemIndex ++;
							}
							ProbabilityGift gift = ProbabilityGift.getProbabilityGift(gifts);
							if(gift == null)continue;
							int itemId = Integer.parseInt(gift.getGiftId());
							if(itemId == 0)continue;//如果得到的是空物品，跳过
							int itemCnt = Integer.parseInt(gift.getGiftCnt());
							if(itemCnt == 0)continue;//如果得到的是物品数量是0，跳过
							ItemEntity itemEntity = new ItemEntity();
							itemEntity.setItemId(itemId);
							itemEntity.setCount(itemCnt);
							dropItem.addItemInfo(itemEntity);
							ItemEntity itemEntity1 = null;
							if(monstersDropItems.containsKey(itemId)) {
								itemEntity1 = monstersDropItems.get(itemId);
							}
							if(itemEntity1 != null) {
								itemEntity1.setCount(itemEntity.getCount() + itemEntity1.getCount());
								monstersDropItems.put(itemId, itemEntity1);
							}else {
								monstersDropItems.put(itemId, itemEntity);
							}
							
						}	
					}
				}
			}
		}
		return dropItem;
	}

	/**
	 * 每个新的回合补满行动力
	 */
	public void reset() {
		for(PlayerFightUnit playerSceneUnit : players.values()){
			playerSceneUnit.setCurrentActionPower(playerSceneUnit.getTotalActionPower());
			playerSceneUnit.shieldStack.clear();
		}
		
		for(FightSceneUnit monsterSceneUnit : getMonsters(realStage)){
			monsterSceneUnit.setCurrentActionPower(monsterSceneUnit.getTotalActionPower());
			if(monsterSceneUnit.isJustDead()){
				monsterSceneUnit.setJustDead(false);
			}
		}
	}
	
	/**
	 * 根据是玩家点击ready还是真正执行游戏更新下个操作的玩家
	 * @param stage
	 */
	public void updateOperIndex(int stage) {
		if(stage == deployStage){
//			if(playerOperIndex == playerOperList.size()-1){
//				playerOperIndex = 0;//最后一个人点了准备 下一个该操作的人变为第一个人
//			}else {
//				playerOperIndex += 1;
//			}
			playerOperIndex = getNextOperIndex();
		}else {
			//找到第一个没死的人
			for(int i = 0; i < playerOperList.size() ; i++){
				String account = playerOperList.get(i);
				PlayerFightUnit playerFightUnit = getPlayers(realStage).get(account);
				if(playerFightUnit.getCurrentHp() > 0){
					playerOperIndex = i;
					return;
				}
			}
		}
	}
	
	
	/**
	 * 找到下一个操作者
	 * @return
	 */
	private int getNextOperIndex() {
		int size = playerOperList.size();
		for(int i = playerOperIndex; i<size ; i++){
			if(i == size -1){
				break;
			}
			String account = playerOperList.get(i+1);
			PlayerFightUnit playerFightUnit = getPlayers(deployStage).get(account);
			if(playerFightUnit.getCurrentHp() > 0){
				playerOperIndex = i+1;
				return i+1;
			}
		}
		//后面没有活着的人了 就找前面的
		for(int i = 0; i <= playerOperIndex ; i++){
			String account = playerOperList.get(i);
			PlayerFightUnit playerFightUnit = getPlayers(deployStage).get(account);
			if(playerFightUnit.getCurrentHp() > 0){
				return i;
			}
		}
		return 0;
	}
	
	/**
	 * 是否是最后一个操作者
	 * @return
	 */
	public boolean checkLastOperatpr(String account) {
		int index = playerOperList.indexOf(account);
		for(int i = index; i<playerOperList.size() -1; i++){
			if(i == playerOperList.size() -1){
				return true;
			}
			String acc = playerOperList.get(i+1);
			PlayerFightUnit playerFightUnit = getPlayers(deployStage).get(acc);
			if(playerFightUnit.getCurrentHp() > 0){
				return false;
			}
		}
		return true;
	}

	/**
	 * 每次攻击检测武器上是否触发第几次攻击
	 * @param playerUnit
	 * @param account
	 * @return
	 */
	public List<Integer> checkDeployTriggerAddTalents(PlayerFightUnit playerUnit,String account,boolean isModify) {
		List<Integer> triggeredTalents = new ArrayList<>();
		Weapon weapon = playerUnit.getSelectWeapon();
		HashMap<Integer, Integer> talentsCountMap = weapon.getAddTalentMap();
		for(Entry<Integer, Integer> entry : talentsCountMap.entrySet()){
			int talentId = entry.getKey();
			int attackCount = entry.getValue();
			//调整的时候不增加攻击次数
			int affterAttackCount = isModify ? attackCount : attackCount+1;
			talentsCountMap.put(entry.getKey(), affterAttackCount);
			//这里的一定是第一种类型的 就是累计攻击次数的
			TalentEffectConfig talentEffectConfig = XMLTemplateService.tallentEffectConfigMap.get(talentId);
			String[] triggerParams = talentEffectConfig.getTrigger().split(",");
			int needCount = Integer.valueOf(triggerParams[1]);
			if(affterAttackCount >= needCount && affterAttackCount % needCount == 0){
				triggeredTalents.add(talentId);
			}
		}
		return triggeredTalents;
	}

	/**
	 * 每次攻击检测武器是否触发连击类型的天赋
	 * @param playerUnit
	 * @param account
	 * @return
	 */
	public List<Integer> checkDeployTriggerSeriAttackTalents(PlayerFightUnit playerUnit, String account) {
		List<Integer> triggeredTalents = new ArrayList<>();
		//已经攻击过的次数 (触发天赋的时候要把此次攻击先计算上)
		int alreadyAttackCount = 0;
		Weapon weapon = playerUnit.getSelectWeapon();
		
		Stack<BattleStep> stack = playerStacks.get(account);
		if(stack != null){
			int size = stack.size();
			for(int i=0;i<size;i++){
				BattleStep step = stack.peek();
				if(step.stepType == BattleStepType.Attact){
					alreadyAttackCount ++;
				}
			}
		}
		
		List<Integer> seriTalentIdList = weapon.getSeriTalentIdList();
		for(Integer talentId : seriTalentIdList){
			TalentEffectConfig talentEffectConfig = XMLTemplateService.tallentEffectConfigMap.get(talentId);
			String[] triggerParams = talentEffectConfig.getTrigger().split(",");
			int needCount = Integer.valueOf(triggerParams[1]);
			if(alreadyAttackCount+1 >= needCount){
				triggeredTalents.add(talentId);
			}
		}
		return triggeredTalents;
	}
	
	/**
	 * 检测部署阶段打到的目标是否有buff和护盾触发的天赋
	 * @param playerUnit
	 * @param tarentEnemy 
	 * @return
	 */
	public List<Integer> checkTriggerAttackTarTalents(PlayerFightUnit playerUnit, FightSceneUnit tarentEnemy) {
		List<Integer> triggeredTalents = new ArrayList<>();
		Weapon weapon = playerUnit.getSelectWeapon();
		HashMap<Integer, Integer> attckBuffTalentMap = weapon.getAttackBuffTalentMap();
		List<Integer> attackShieldTalentList = weapon.getAttackShieldTalentList();
		for(Entry<Integer, Integer> entry : attckBuffTalentMap.entrySet()){
			if(tarentEnemy.getBuffCountById(entry.getValue()) > 0){
				triggeredTalents.add(entry.getKey());
			}
		}
		
		for(Integer talentId : attackShieldTalentList){
			if(tarentEnemy.getShield() != null){
				triggeredTalents.add(talentId);
			}
		}
		return triggeredTalents;
	}
	
	/**
	 * 检测部署阶段打到的目标是否有buff和护盾触发的天赋
	 * @param playerUnit
	 * @param tarentEnemy 
	 * @param weaponCfgId 
	 * @return
	 */
	public List<Integer> checkRealTimeTriggerAttackTarTalents(PlayerFightUnit playerUnit, FightSceneUnit tarentEnemy, int weaponCfgId) {
		List<Integer> triggeredTalents = new ArrayList<>();
		Weapon weapon = playerUnit.getWeaponByCfgId(weaponCfgId);
		HashMap<Integer, Integer> attckBuffTalentMap = weapon.getAttackBuffTalentMap();
		List<Integer> attackShieldTalentList = weapon.getAttackShieldTalentList();
		for(Entry<Integer, Integer> entry : attckBuffTalentMap.entrySet()){
			if(tarentEnemy.getBuffCountById(entry.getValue()) > 0){
				triggeredTalents.add(entry.getKey());
			}
		}
		
		for(Integer talentId : attackShieldTalentList){
			if(tarentEnemy.getShield() != null){
				triggeredTalents.add(talentId);
			}
		}
		return triggeredTalents;
	}
	
	/**
	 * 真正执行时检测触发天赋（连击）
	 * @param attackerUnit
	 * @param attackCount
	 * @param weaponCfgId 
	 * @return
	 */
	private List<Integer> checkRealTimeTriggerSeriAttackTalents(
			PlayerFightUnit playerUnit, int attackCount, int weaponCfgId) {
		List<Integer> triggeredTalents = new ArrayList<>();
		//已经攻击过的次数 (触发天赋的时候要把此次攻击先计算上)
		int alreadyAttackCount = attackCount;
		Weapon weapon = playerUnit.getWeaponByCfgId(weaponCfgId);;
		
		List<Integer> seriTalentIdList = weapon.getSeriTalentIdList();
		for(Integer talentId : seriTalentIdList){
			TalentEffectConfig talentEffectConfig = XMLTemplateService.tallentEffectConfigMap.get(talentId);
			String[] triggerParams = talentEffectConfig.getTrigger().split(",");
			int needCount = Integer.valueOf(triggerParams[1]);
			if(alreadyAttackCount >= needCount){
				triggeredTalents.add(talentId);
			}
		}
		return triggeredTalents;
	}

	/**
	 * 真正执行时检测触发累计次数天赋
	 * @param weaponCfgId 
	 * @param attackerUnit
	 * @return
	 */
	private List<Integer> checkRealTimeTriggerAddTalents(
			PlayerFightUnit playerUnit, int weaponCfgId) {
		List<Integer> triggeredTalents = new ArrayList<>();
		Weapon weapon =  playerUnit.getWeaponByCfgId(weaponCfgId);
		HashMap<Integer, Integer> talentsCountMap = weapon.getAddTalentMap();
		for(Entry<Integer, Integer> entry : talentsCountMap.entrySet()){
			int talentId = entry.getKey();
			int attackCount = entry.getValue();
			//调整的时候不增加攻击次数
			int affterAttackCount = attackCount+1;
			talentsCountMap.put(entry.getKey(), affterAttackCount);
			//这里的一定是第一种类型的 就是累计攻击次数的
			TalentEffectConfig talentEffectConfig = XMLTemplateService.tallentEffectConfigMap.get(talentId);
			String[] triggerParams = talentEffectConfig.getTrigger().split(",");
			int needCount = Integer.valueOf(triggerParams[1]);
			if(affterAttackCount >= needCount && affterAttackCount % needCount == 0){
				triggeredTalents.add(talentId);
			}
		}
		return triggeredTalents;
	}

	/**
	 * 增加回合数
	 */
	public void addBattleRound() {
		battleRound++;
	}

	
}
